ia64/xen-unstable

changeset 2665:49fa29c29184

bitkeeper revision 1.1159.1.243 (41761dd6FhmRMJyuSuwaKjjF1oicDQ)

Fix GDT checking so that we check ownership before zapping reserved entries
(bug pointed out by Michael Vrable). Also map_domain_mem() isn't used across
a 'goto fail' any more, so the error-exit path is now correct.
author kaf24@freefall.cl.cam.ac.uk
date Wed Oct 20 08:12:06 2004 +0000 (2004-10-20)
parents e979bf071ca4
children d10a9677a639
files xen/arch/x86/x86_32/mm.c
line diff
     1.1 --- a/xen/arch/x86/x86_32/mm.c	Tue Oct 19 17:35:10 2004 +0000
     1.2 +++ b/xen/arch/x86/x86_32/mm.c	Wed Oct 20 08:12:06 2004 +0000
     1.3 @@ -259,23 +259,39 @@ long set_gdt(struct domain *d,
     1.4               unsigned int entries)
     1.5  {
     1.6      /* NB. There are 512 8-byte entries per GDT page. */
     1.7 -    int i, nr_pages = (entries + 511) / 512;
     1.8 +    int i = 0, nr_pages = (entries + 511) / 512;
     1.9      struct desc_struct *vgdt;
    1.10 +    unsigned long pfn;
    1.11  
    1.12 -    vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
    1.13 -    memset( vgdt + FIRST_RESERVED_GDT_ENTRY, 0,	    
    1.14 -           NR_RESERVED_GDT_ENTRIES*8);
    1.15 +    /* Check the first page in the new GDT. */
    1.16 +    if ( (pfn = frames[0]) >= max_page )
    1.17 +        goto fail;
    1.18  
    1.19 -    /* Check the new GDT. */
    1.20 -    for ( i = 0; i < nr_pages; i++ )
    1.21 +    /* The first page is special because Xen owns a range of entries in it. */
    1.22 +    if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
    1.23      {
    1.24 -        if ( unlikely(frames[i] >= max_page) ||
    1.25 -             unlikely(!get_page_and_type(&frame_table[frames[i]], 
    1.26 -                                         d, PGT_gdt_page)) )
    1.27 +        /* GDT checks failed: try zapping the Xen reserved entries. */
    1.28 +        if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) )
    1.29 +            goto fail;
    1.30 +        vgdt = map_domain_mem(pfn << PAGE_SHIFT);
    1.31 +        memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0,
    1.32 +               NR_RESERVED_GDT_ENTRIES*8);
    1.33 +        unmap_domain_mem(vgdt);
    1.34 +        put_page_and_type(&frame_table[pfn]);
    1.35 +
    1.36 +        /* Okay, we zapped the entries. Now try the GDT checks again. */
    1.37 +        if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
    1.38              goto fail;
    1.39      }
    1.40  
    1.41 +    /* Check the remaining pages in the new GDT. */
    1.42 +    for ( i = 1; i < nr_pages; i++ )
    1.43 +        if ( ((pfn = frames[i]) >= max_page) ||
    1.44 +             !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
    1.45 +            goto fail;
    1.46 +
    1.47      /* Copy reserved GDT entries to the new GDT. */
    1.48 +    vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
    1.49      memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, 
    1.50             gdt_table + FIRST_RESERVED_GDT_ENTRY, 
    1.51             NR_RESERVED_GDT_ENTRIES*8);