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