ia64/xen-unstable

changeset 10101:1855124935e2

Fix a crash in gdbserver-xen where it references unmapped memory if
the page directory / page table pages are not present (for example
through dereferencing NULL in the gdb session). Changes:

- map_domain_va_32 has been rewritten to match map_domain_va_pae and
map_domain_va_64.

- All three functions have been extended to handle multiple vCPUs,
(untested, but shuld work), and check for _PAGE_PRESENT.

- Keir's workaround for the compile error in map_domain_va_64 has been
removed and hopefully fixed.

Signed-Off-By: Simon Kagstrom <simon.kagstrom@bth.se>
author kaf24@firebug.cl.cam.ac.uk
date Fri May 19 15:22:11 2006 +0100 (2006-05-19)
parents aa17b7173325
children b736d3335641
files tools/libxc/xc_ptrace.c
line diff
     1.1 --- a/tools/libxc/xc_ptrace.c	Thu May 18 21:41:56 2006 +0100
     1.2 +++ b/tools/libxc/xc_ptrace.c	Fri May 19 15:22:11 2006 +0100
     1.3 @@ -185,61 +185,34 @@ map_domain_va_32(
     1.4      void *guest_va,
     1.5      int perm)
     1.6  {
     1.7 -    unsigned long pde, page;
     1.8 -    unsigned long va = (unsigned long)guest_va;
     1.9 -
    1.10 -    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
    1.11 -    static uint32_t *cr3_virt[MAX_VIRT_CPUS];
    1.12 -    static unsigned long  pde_phys[MAX_VIRT_CPUS];
    1.13 -    static uint32_t *pde_virt[MAX_VIRT_CPUS];
    1.14 -    static unsigned long  page_phys[MAX_VIRT_CPUS];
    1.15 -    static uint32_t *page_virt[MAX_VIRT_CPUS];
    1.16 -    static int            prev_perm[MAX_VIRT_CPUS];
    1.17 +    unsigned long l1p, p, va = (unsigned long)guest_va;
    1.18 +    uint32_t *l2, *l1;
    1.19 +    static void *v[MAX_VIRT_CPUS];
    1.20  
    1.21 -   if (ctxt[cpu].ctrlreg[3] == 0)
    1.22 -       return NULL;
    1.23 -   if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] )
    1.24 -    {
    1.25 -        cr3_phys[cpu] = ctxt[cpu].ctrlreg[3];
    1.26 -        if ( cr3_virt[cpu] )
    1.27 -            munmap(cr3_virt[cpu], PAGE_SIZE);
    1.28 -        cr3_virt[cpu] = xc_map_foreign_range(
    1.29 -            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
    1.30 -            cr3_phys[cpu] >> PAGE_SHIFT);
    1.31 -        if ( cr3_virt[cpu] == NULL )
    1.32 -            return NULL;
    1.33 -    }
    1.34 -    pde = to_ma(cpu, cr3_virt[cpu][vtopdi(va)]);
    1.35 -    if ( pde != pde_phys[cpu] )
    1.36 -    {
    1.37 -        pde_phys[cpu] = pde;
    1.38 -        if ( pde_virt[cpu] )
    1.39 -            munmap(pde_virt[cpu], PAGE_SIZE);
    1.40 -        pde_virt[cpu] = xc_map_foreign_range(
    1.41 -            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
    1.42 -            pde_phys[cpu] >> PAGE_SHIFT);
    1.43 -        if ( pde_virt[cpu] == NULL )
    1.44 -            return NULL;
    1.45 -    }
    1.46 -    page = to_ma(cpu, pde_virt[cpu][vtopti(va)]);
    1.47 +    l2 = xc_map_foreign_range(
    1.48 +         xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT);
    1.49 +    if ( l2 == NULL )
    1.50 +        return NULL;
    1.51  
    1.52 -    if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) )
    1.53 -    {
    1.54 -        page_phys[cpu] = page;
    1.55 -        if ( page_virt[cpu] )
    1.56 -            munmap(page_virt[cpu], PAGE_SIZE);
    1.57 -        page_virt[cpu] = xc_map_foreign_range(
    1.58 -            xc_handle, current_domid, PAGE_SIZE, perm,
    1.59 -            page_phys[cpu] >> PAGE_SHIFT);
    1.60 -        if ( page_virt[cpu] == NULL )
    1.61 -        {
    1.62 -            page_phys[cpu] = 0;
    1.63 -            return NULL;
    1.64 -        }
    1.65 -        prev_perm[cpu] = perm;
    1.66 -    }
    1.67 +    l1p = to_ma(cpu, l2[l2_table_offset(va)]);
    1.68 +    munmap(l2, PAGE_SIZE);
    1.69 +    if ( !(l1p & _PAGE_PRESENT) )
    1.70 +        return NULL;
    1.71 +    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l1p >> PAGE_SHIFT);
    1.72 +    if ( l1 == NULL )
    1.73 +        return NULL;
    1.74  
    1.75 -    return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
    1.76 +    p = to_ma(cpu, l1[l1_table_offset(va)]);
    1.77 +    munmap(l1, PAGE_SIZE);
    1.78 +    if ( !(p & _PAGE_PRESENT) )
    1.79 +        return NULL;
    1.80 +    if ( v[cpu] != NULL )
    1.81 +        munmap(v[cpu], PAGE_SIZE);
    1.82 +    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
    1.83 +    if ( v[cpu] == NULL )
    1.84 +        return NULL;
    1.85 +
    1.86 +    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
    1.87  }
    1.88  
    1.89  
    1.90 @@ -252,7 +225,7 @@ map_domain_va_pae(
    1.91  {
    1.92      unsigned long l2p, l1p, p, va = (unsigned long)guest_va;
    1.93      uint64_t *l3, *l2, *l1;
    1.94 -    static void *v;
    1.95 +    static void *v[MAX_VIRT_CPUS];
    1.96  
    1.97      l3 = xc_map_foreign_range(
    1.98          xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT);
    1.99 @@ -260,26 +233,32 @@ map_domain_va_pae(
   1.100          return NULL;
   1.101  
   1.102      l2p = to_ma(cpu, l3[l3_table_offset_pae(va)]);
   1.103 +    munmap(l3, PAGE_SIZE);
   1.104 +    if ( !(l2p & _PAGE_PRESENT) )
   1.105 +        return NULL;
   1.106      l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p >> PAGE_SHIFT);
   1.107 -    munmap(l3, PAGE_SIZE);
   1.108      if ( l2 == NULL )
   1.109          return NULL;
   1.110  
   1.111      l1p = to_ma(cpu, l2[l2_table_offset_pae(va)]);
   1.112 +    munmap(l2, PAGE_SIZE);
   1.113 +    if ( !(l1p & _PAGE_PRESENT) )
   1.114 +        return NULL;
   1.115      l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p >> PAGE_SHIFT);
   1.116 -    munmap(l2, PAGE_SIZE);
   1.117      if ( l1 == NULL )
   1.118          return NULL;
   1.119  
   1.120      p = to_ma(cpu, l1[l1_table_offset_pae(va)]);
   1.121 -    if ( v != NULL )
   1.122 -        munmap(v, PAGE_SIZE);
   1.123 -    v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.124      munmap(l1, PAGE_SIZE);
   1.125 -    if ( v == NULL )
   1.126 +    if ( !(p & _PAGE_PRESENT) )
   1.127 +        return NULL;
   1.128 +    if ( v[cpu] != NULL )
   1.129 +        munmap(v[cpu], PAGE_SIZE);
   1.130 +    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.131 +    if ( v[cpu] == NULL )
   1.132          return NULL;
   1.133  
   1.134 -    return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1)));
   1.135 +    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
   1.136  }
   1.137  
   1.138  #ifdef __x86_64__
   1.139 @@ -292,7 +271,7 @@ map_domain_va_64(
   1.140  {
   1.141      unsigned long l3p, l2p, l1p, l1e, p, va = (unsigned long)guest_va;
   1.142      uint64_t *l4, *l3, *l2, *l1;
   1.143 -    static void *v;
   1.144 +    static void *v[MAX_VIRT_CPUS];
   1.145  
   1.146      if ((ctxt[cpu].ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */
   1.147          return map_domain_va_32(xc_handle, cpu, guest_va, perm);
   1.148 @@ -303,24 +282,33 @@ map_domain_va_64(
   1.149          return NULL;
   1.150  
   1.151      l3p = to_ma(cpu, l4[l4_table_offset(va)]);
   1.152 +    munmap(l4, PAGE_SIZE);
   1.153 +    if ( !(l3p & _PAGE_PRESENT) )
   1.154 +        return NULL;
   1.155      l3 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l3p >> PAGE_SHIFT);
   1.156 -    munmap(l4, PAGE_SIZE);
   1.157      if ( l3 == NULL )
   1.158          return NULL;
   1.159  
   1.160      l2p = to_ma(cpu, l3[l3_table_offset(va)]);
   1.161 +    munmap(l3, PAGE_SIZE);
   1.162 +    if ( !(l2p & _PAGE_PRESENT) )
   1.163 +        return NULL;
   1.164      l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p >> PAGE_SHIFT);
   1.165 -    munmap(l3, PAGE_SIZE);
   1.166      if ( l2 == NULL )
   1.167          return NULL;
   1.168  
   1.169      l1 = NULL;
   1.170      l1e = to_ma(cpu, l2[l2_table_offset(va)]);
   1.171 +    if ( !(l1e & _PAGE_PRESENT) )
   1.172 +    {
   1.173 +        munmap(l2, PAGE_SIZE);
   1.174 +        return NULL;
   1.175 +    }
   1.176      l1p = l1e >> PAGE_SHIFT;
   1.177      if (l1e & 0x80)  { /* 2M pages */
   1.178          p = to_ma(cpu, (l1p + l1_table_offset(va)) << PAGE_SHIFT);
   1.179      } else { /* 4K pages */
   1.180 -        //l1p = to_ma(cpu, l1e[l1_table_offset(va)]);
   1.181 +        l1p = to_ma(cpu, l1p);
   1.182          l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p >> PAGE_SHIFT);
   1.183          munmap(l2, PAGE_SIZE);
   1.184          if ( l1 == NULL )
   1.185 @@ -328,15 +316,15 @@ map_domain_va_64(
   1.186  
   1.187          p = to_ma(cpu, l1[l1_table_offset(va)]);
   1.188      }
   1.189 -    if ( v != NULL )
   1.190 -        munmap(v, PAGE_SIZE);
   1.191 -    v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.192 +    if ( v[cpu] != NULL )
   1.193 +        munmap(v[cpu], PAGE_SIZE);
   1.194 +    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.195      if (l1)
   1.196          munmap(l1, PAGE_SIZE);
   1.197 -    if ( v == NULL )
   1.198 +    if ( v[cpu] == NULL )
   1.199          return NULL;
   1.200  
   1.201 -    return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1)));
   1.202 +    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
   1.203  }
   1.204  #endif
   1.205