ia64/xen-unstable

changeset 19236:9559343fe5e8

libxc: xc_ptrace cleanup

There are some bugs in PTRACE_PEEK/POKE.
- can't track 2MB pages in 32bit pae mode.
- leakage of mmap/munmap.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Feb 20 11:09:46 2009 +0000 (2009-02-20)
parents 596f21d901f3
children 07e65892fc8e
files tools/libxc/xc_ptrace.c
line diff
     1.1 --- a/tools/libxc/xc_ptrace.c	Fri Feb 20 11:08:31 2009 +0000
     1.2 +++ b/tools/libxc/xc_ptrace.c	Fri Feb 20 11:09:46 2009 +0000
     1.3 @@ -149,173 +149,6 @@ online_vcpus_changed(uint64_t cpumap)
     1.4  
     1.5  }
     1.6  
     1.7 -/* --------------------- */
     1.8 -/* XXX application state */
     1.9 -static long      nr_pages = 0;
    1.10 -static uint64_t *page_array = NULL;
    1.11 -
    1.12 -static uint64_t to_ma(int cpu, uint64_t maddr)
    1.13 -{
    1.14 -    return maddr;
    1.15 -}
    1.16 -
    1.17 -static void *
    1.18 -map_domain_va_32(
    1.19 -    int xc_handle,
    1.20 -    int cpu,
    1.21 -    void *guest_va,
    1.22 -    int perm)
    1.23 -{
    1.24 -    unsigned long l2e, l1e, l1p, p, va = (unsigned long)guest_va;
    1.25 -    uint32_t *l2, *l1;
    1.26 -    static void *v[MAX_VIRT_CPUS];
    1.27 -
    1.28 -    l2 = xc_map_foreign_range(
    1.29 -         xc_handle, current_domid, PAGE_SIZE, PROT_READ,
    1.30 -         xen_cr3_to_pfn(ctxt[cpu].c.ctrlreg[3]));
    1.31 -    if ( l2 == NULL )
    1.32 -        return NULL;
    1.33 -
    1.34 -    l2e = l2[l2_table_offset_i386(va)];
    1.35 -    munmap(l2, PAGE_SIZE);
    1.36 -    if ( !(l2e & _PAGE_PRESENT) )
    1.37 -        return NULL;
    1.38 -    l1p = to_ma(cpu, l2e);
    1.39 -    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l1p >> PAGE_SHIFT);
    1.40 -    if ( l1 == NULL )
    1.41 -        return NULL;
    1.42 -
    1.43 -    l1e = l1[l1_table_offset_i386(va)];
    1.44 -    munmap(l1, PAGE_SIZE);
    1.45 -    if ( !(l1e & _PAGE_PRESENT) )
    1.46 -        return NULL;
    1.47 -    p = to_ma(cpu, l1e);
    1.48 -    if ( v[cpu] != NULL )
    1.49 -        munmap(v[cpu], PAGE_SIZE);
    1.50 -    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
    1.51 -    if ( v[cpu] == NULL )
    1.52 -        return NULL;
    1.53 -
    1.54 -    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
    1.55 -}
    1.56 -
    1.57 -
    1.58 -static void *
    1.59 -map_domain_va_pae(
    1.60 -    int xc_handle,
    1.61 -    int cpu,
    1.62 -    void *guest_va,
    1.63 -    int perm)
    1.64 -{
    1.65 -    uint64_t l3e, l2e, l1e, l2p, l1p, p;
    1.66 -    unsigned long va = (unsigned long)guest_va;
    1.67 -    uint64_t *l3, *l2, *l1;
    1.68 -    static void *v[MAX_VIRT_CPUS];
    1.69 -
    1.70 -    l3 = xc_map_foreign_range(
    1.71 -        xc_handle, current_domid, PAGE_SIZE, PROT_READ,
    1.72 -        xen_cr3_to_pfn(ctxt[cpu].c.ctrlreg[3]));
    1.73 -    if ( l3 == NULL )
    1.74 -        return NULL;
    1.75 -
    1.76 -    l3e = l3[l3_table_offset_pae(va)];
    1.77 -    munmap(l3, PAGE_SIZE);
    1.78 -    if ( !(l3e & _PAGE_PRESENT) )
    1.79 -        return NULL;
    1.80 -    l2p = to_ma(cpu, l3e);
    1.81 -    l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p >> PAGE_SHIFT);
    1.82 -    if ( l2 == NULL )
    1.83 -        return NULL;
    1.84 -
    1.85 -    l2e = l2[l2_table_offset_pae(va)];
    1.86 -    munmap(l2, PAGE_SIZE);
    1.87 -    if ( !(l2e & _PAGE_PRESENT) )
    1.88 -        return NULL;
    1.89 -    l1p = to_ma(cpu, l2e);
    1.90 -    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l1p >> PAGE_SHIFT);
    1.91 -    if ( l1 == NULL )
    1.92 -        return NULL;
    1.93 -
    1.94 -    l1e = l1[l1_table_offset_pae(va)];
    1.95 -    munmap(l1, PAGE_SIZE);
    1.96 -    if ( !(l1e & _PAGE_PRESENT) )
    1.97 -        return NULL;
    1.98 -    p = to_ma(cpu, l1e);
    1.99 -    if ( v[cpu] != NULL )
   1.100 -        munmap(v[cpu], PAGE_SIZE);
   1.101 -    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.102 -    if ( v[cpu] == NULL )
   1.103 -        return NULL;
   1.104 -
   1.105 -    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
   1.106 -}
   1.107 -
   1.108 -#ifdef __x86_64__
   1.109 -static void *
   1.110 -map_domain_va_64(
   1.111 -    int xc_handle,
   1.112 -    int cpu,
   1.113 -    void *guest_va,
   1.114 -    int perm)
   1.115 -{
   1.116 -    unsigned long l4e, l3e, l2e, l1e, l3p, l2p, l1p, p, va = (unsigned long)guest_va;
   1.117 -    uint64_t *l4, *l3, *l2, *l1;
   1.118 -    static void *v[MAX_VIRT_CPUS];
   1.119 -
   1.120 -    if ((ctxt[cpu].c.ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */
   1.121 -        return map_domain_va_32(xc_handle, cpu, guest_va, perm);
   1.122 -
   1.123 -    l4 = xc_map_foreign_range(
   1.124 -        xc_handle, current_domid, PAGE_SIZE, PROT_READ,
   1.125 -        xen_cr3_to_pfn(ctxt[cpu].c.ctrlreg[3]));
   1.126 -    if ( l4 == NULL )
   1.127 -        return NULL;
   1.128 -
   1.129 -    l4e = l4[l4_table_offset(va)];
   1.130 -    munmap(l4, PAGE_SIZE);
   1.131 -    if ( !(l4e & _PAGE_PRESENT) )
   1.132 -        return NULL;
   1.133 -    l3p = to_ma(cpu, l4e);
   1.134 -    l3 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l3p >> PAGE_SHIFT);
   1.135 -    if ( l3 == NULL )
   1.136 -        return NULL;
   1.137 -
   1.138 -    l3e = l3[l3_table_offset(va)];
   1.139 -    munmap(l3, PAGE_SIZE);
   1.140 -    if ( !(l3e & _PAGE_PRESENT) )
   1.141 -        return NULL;
   1.142 -    l2p = to_ma(cpu, l3e);
   1.143 -    l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p >> PAGE_SHIFT);
   1.144 -    if ( l2 == NULL )
   1.145 -        return NULL;
   1.146 -
   1.147 -    l2e = l2[l2_table_offset(va)];
   1.148 -    munmap(l2, PAGE_SIZE);
   1.149 -    if ( !(l2e & _PAGE_PRESENT) )
   1.150 -        return NULL;
   1.151 -    l1p = to_ma(cpu, l2e);
   1.152 -    if (l2e & 0x80)  { /* 2M pages */
   1.153 -        p = to_ma(cpu, l1p + (l1_table_offset(va) << PAGE_SHIFT));
   1.154 -    } else { /* 4K pages */
   1.155 -        l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l1p >> PAGE_SHIFT);
   1.156 -        if ( l1 == NULL )
   1.157 -            return NULL;
   1.158 -
   1.159 -        l1e = l1[l1_table_offset(va)];
   1.160 -        munmap(l1, PAGE_SIZE);
   1.161 -        if ( !(l1e & _PAGE_PRESENT) )
   1.162 -            return NULL;
   1.163 -        p = to_ma(cpu, l1e);
   1.164 -    }
   1.165 -    if ( v[cpu] != NULL )
   1.166 -        munmap(v[cpu], PAGE_SIZE);
   1.167 -    v[cpu] = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p >> PAGE_SHIFT);
   1.168 -    if ( v[cpu] == NULL )
   1.169 -        return NULL;
   1.170 -
   1.171 -    return (void *)((unsigned long)v[cpu] | (va & (PAGE_SIZE - 1)));
   1.172 -}
   1.173 -#endif
   1.174  
   1.175  static void *
   1.176  map_domain_va(
   1.177 @@ -324,68 +157,30 @@ map_domain_va(
   1.178      void *guest_va,
   1.179      int perm)
   1.180  {
   1.181 -    unsigned long va = (unsigned long) guest_va;
   1.182 -    long npgs = xc_get_tot_pages(xc_handle, current_domid);
   1.183 -    static enum { MODE_UNKNOWN, MODE_64, MODE_32, MODE_PAE } mode;
   1.184 -
   1.185 -    if ( mode == MODE_UNKNOWN )
   1.186 -    {
   1.187 -        xen_capabilities_info_t caps;
   1.188 -        (void)xc_version(xc_handle, XENVER_capabilities, caps);
   1.189 -        if ( strstr(caps, "-x86_64") )
   1.190 -            mode = MODE_64;
   1.191 -        else if ( strstr(caps, "-x86_32p") )
   1.192 -            mode = MODE_PAE;
   1.193 -        else if ( strstr(caps, "-x86_32") )
   1.194 -            mode = MODE_32;
   1.195 -    }
   1.196 +    unsigned long va = (unsigned long)guest_va;
   1.197 +    unsigned long mfn;
   1.198 +    void *map;
   1.199  
   1.200 -    if ( nr_pages != npgs )
   1.201 -    {
   1.202 -        if ( nr_pages > 0 )
   1.203 -            free(page_array);
   1.204 -        nr_pages = npgs;
   1.205 -        if ( (page_array = malloc(nr_pages * sizeof(*page_array))) == NULL )
   1.206 -        {
   1.207 -            IPRINTF("Could not allocate memory\n");
   1.208 -            return NULL;
   1.209 -        }
   1.210 -        if ( xc_get_pfn_list(xc_handle, current_domid,
   1.211 -                             page_array, nr_pages) != nr_pages )
   1.212 -        {
   1.213 -            IPRINTF("Could not get the page frame list\n");
   1.214 -            return NULL;
   1.215 -        }
   1.216 -    }
   1.217 +    /* cross page boundary */
   1.218 +    if ( (va & ~PAGE_MASK) + sizeof(long) > PAGE_SIZE )
   1.219 +        return NULL;
   1.220  
   1.221 -    if (fetch_regs(xc_handle, cpu, NULL))
   1.222 +    mfn = xc_translate_foreign_address(xc_handle, current_domid, cpu, va);
   1.223 +    if ( mfn == 0 )
   1.224          return NULL;
   1.225  
   1.226 -    if (!paging_enabled(&ctxt[cpu])) {
   1.227 -        static void * v;
   1.228 -        uint64_t page;
   1.229 -
   1.230 -        if ( v != NULL )
   1.231 -            munmap(v, PAGE_SIZE);
   1.232 -
   1.233 -        page = to_ma(cpu, va);
   1.234 -
   1.235 -        v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
   1.236 -                perm, page >> PAGE_SHIFT);
   1.237 +    map = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, 
   1.238 +                               perm, mfn);
   1.239 +    if (map == NULL)
   1.240 +        return NULL;
   1.241  
   1.242 -        if ( v == NULL )
   1.243 -            return NULL;
   1.244 +    return map + (va & ~PAGE_MASK);
   1.245 +}
   1.246  
   1.247 -        return (void *)(((unsigned long)v) | (va & BSD_PAGE_MASK));
   1.248 -    }
   1.249 -#ifdef __x86_64__
   1.250 -    if ( mode == MODE_64 )
   1.251 -        return map_domain_va_64(xc_handle, cpu, guest_va, perm);
   1.252 -#endif
   1.253 -    if ( mode == MODE_PAE )
   1.254 -        return map_domain_va_pae(xc_handle, cpu, guest_va, perm);
   1.255 -    /* else ( mode == MODE_32 ) */
   1.256 -    return map_domain_va_32(xc_handle, cpu, guest_va, perm);
   1.257 +static void
   1.258 +unmap_domain_va(void *guest_va)
   1.259 +{
   1.260 +    munmap((void *)((unsigned long)guest_va & PAGE_MASK), PAGE_SIZE);
   1.261  }
   1.262  
   1.263  int control_c_pressed_flag = 0;
   1.264 @@ -473,6 +268,8 @@ xc_ptrace(
   1.265          if ( guest_va == NULL )
   1.266              goto out_error;
   1.267          retval = *guest_va;
   1.268 +        if (!current_isfile)
   1.269 +            unmap_domain_va(guest_va);
   1.270          break;
   1.271  
   1.272      case PTRACE_POKETEXT:
   1.273 @@ -486,7 +283,9 @@ xc_ptrace(
   1.274                  xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
   1.275          if ( guest_va == NULL )
   1.276              goto out_error;
   1.277 -        *guest_va = (unsigned long)data;
   1.278 +        *guest_va = edata;
   1.279 +        if (!current_isfile)
   1.280 +            unmap_domain_va(guest_va);
   1.281          break;
   1.282  
   1.283      case PTRACE_GETREGS: