[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] add get_page() to prevent from freeing page



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 535b466ee1ef431bbb82b0bdea1b3c90a85914b3
# Parent  d60da6514d65c8bf577d136adc720b1dc6c28388
[IA64] add get_page() to prevent from freeing page

get_page() when access a page of domain.
pages can be removed from domain and freed by another cpu.
To prevent accessing freeing page, use get_page() and put_page()

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 xen/arch/ia64/vmx/vmmu.c          |   22 ++++++++++++++++++----
 xen/arch/ia64/vmx/vmx_hypercall.c |    6 ++++++
 xen/arch/ia64/xen/fw_emul.c       |   35 +++++++++++++++++++++++++++++------
 xen/arch/ia64/xen/vcpu.c          |   23 ++++++++++++++++++++---
 4 files changed, 73 insertions(+), 13 deletions(-)

diff -r d60da6514d65 -r 535b466ee1ef xen/arch/ia64/vmx/vmmu.c
--- a/xen/arch/ia64/vmx/vmmu.c  Mon Jun 19 13:00:37 2006 -0600
+++ b/xen/arch/ia64/vmx/vmmu.c  Mon Jun 19 13:06:53 2006 -0600
@@ -313,7 +313,9 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *cod
     u64     *vpa;
     thash_data_t    *tlb;
     u64     mfn;
-
+    struct page_info* page;
+
+ again:
     if ( !(VCPU(vcpu, vpsr) & IA64_PSR_IT) ) {   // I-side physical mode
         gpip = gip;
     }
@@ -327,15 +329,27 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *cod
     if( gpip){
         mfn = gmfn_to_mfn(vcpu->domain, gpip >>PAGE_SHIFT);
         if( mfn == INVALID_MFN )  panic_domain(vcpu_regs(vcpu),"fetch_code: 
invalid memory\n");
-        vpa =(u64 *)__va( (gip & (PAGE_SIZE-1)) | (mfn<<PAGE_SHIFT));
     }else{
         tlb = vhpt_lookup(gip);
         if( tlb == NULL)
             panic_domain(vcpu_regs(vcpu),"No entry found in ITLB and DTLB\n");
-        vpa =(u64 
*)__va((tlb->ppn>>(PAGE_SHIFT-ARCH_PAGE_SHIFT)<<PAGE_SHIFT)|(gip&(PAGE_SIZE-1)));
-    }
+        mfn = tlb->ppn >> (PAGE_SHIFT - ARCH_PAGE_SHIFT);
+    }
+
+    page = mfn_to_page(mfn);
+    if (get_page(page, vcpu->domain) == 0) {
+        if (page_get_owner(page) != vcpu->domain) {
+            // This page might be a page granted by another domain.
+            panic_domain(NULL, "domain tries to execute foreign domain "
+                         "page which might be mapped by grant table.\n");
+        }
+        goto again;
+    }
+    vpa = (u64 *)__va((mfn << PAGE_SHIFT) | (gip & (PAGE_SIZE - 1)));
+
     *code1 = *vpa++;
     *code2 = *vpa;
+    put_page(page);
     return 1;
 }
 
diff -r d60da6514d65 -r 535b466ee1ef xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Mon Jun 19 13:00:37 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Mon Jun 19 13:06:53 2006 -0600
@@ -160,10 +160,15 @@ static int do_set_shared_page(VCPU *vcpu
     u64 o_info;
     struct domain *d = vcpu->domain;
     struct vcpu *v;
+    struct page_info *page;
     if(vcpu->domain!=dom0)
         return -EPERM;
     o_info = (u64)vcpu->domain->shared_info;
+ again:
     d->shared_info= (shared_info_t *)domain_mpa_to_imva(vcpu->domain, gpa);
+    page = virt_to_page(d->shared_info);
+    if (get_page(page, d) == 0)
+        goto again;
 
     /* Copy existing shared info into new page */
     if (o_info) {
@@ -178,6 +183,7 @@ static int do_set_shared_page(VCPU *vcpu
                free_xenheap_page((void *)o_info);
     } else
         memset(d->shared_info, 0, PAGE_SIZE);
+    put_page(page);
     return 0;
 }
 
diff -r d60da6514d65 -r 535b466ee1ef xen/arch/ia64/xen/fw_emul.c
--- a/xen/arch/ia64/xen/fw_emul.c       Mon Jun 19 13:00:37 2006 -0600
+++ b/xen/arch/ia64/xen/fw_emul.c       Mon Jun 19 13:06:53 2006 -0600
@@ -359,18 +359,32 @@ xen_pal_emulator(unsigned long index, u6
 
 // given a current domain (virtual or metaphysical) address, return the 
virtual address
 static unsigned long
-efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault)
+efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault,
+                         struct page_info** page)
 {
        struct vcpu *v = current;
        unsigned long mpaddr = domain_addr;
+       unsigned long virt;
        *fault = IA64_NO_FAULT;
 
+again:
        if (v->domain->arch.efi_virt_mode) {
                *fault = vcpu_tpa(v, domain_addr, &mpaddr);
                if (*fault != IA64_NO_FAULT) return 0;
        }
 
-       return ((unsigned long) __va(translate_domain_mpaddr(mpaddr, NULL)));
+       virt = domain_mpa_to_imva(v->domain, mpaddr);
+       *page = virt_to_page(virt);
+       if (get_page(*page, current->domain) == 0) {
+               if (page_get_owner(*page) != current->domain) {
+                       // which code is appropriate?
+                       *fault = IA64_FAULT;
+                       return 0;
+               }
+               goto again;
+       }
+
+       return virt;
 }
 
 static efi_status_t
@@ -379,18 +393,27 @@ efi_emulate_get_time(
        IA64FAULT *fault)
 {
        unsigned long tv = 0, tc = 0;
+       struct page_info *tv_page = NULL;
+       struct page_info *tc_page = NULL;
        efi_status_t status;
 
        //printf("efi_get_time(%016lx,%016lx) called\n", tv_addr, tc_addr);
-       tv = efi_translate_domain_addr(tv_addr, fault);
-       if (*fault != IA64_NO_FAULT) return 0;
+       tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
+       if (*fault != IA64_NO_FAULT)
+               return 0;
        if (tc_addr) {
-               tc = efi_translate_domain_addr(tc_addr, fault);
-               if (*fault != IA64_NO_FAULT) return 0;
+               tc = efi_translate_domain_addr(tc_addr, fault, &tc_page);
+               if (*fault != IA64_NO_FAULT) {
+                       put_page(tv_page);
+                       return 0;
+               }
        }
        //printf("efi_get_time(%016lx,%016lx) translated to xen virtual 
address\n", tv, tc);
        status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc);
        //printf("efi_get_time returns %lx\n", status);
+       if (tc_page != NULL)
+               put_page(tc_page);
+       put_page(tv_page);
        return status;
 }
 
diff -r d60da6514d65 -r 535b466ee1ef xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c  Mon Jun 19 13:00:37 2006 -0600
+++ b/xen/arch/ia64/xen/vcpu.c  Mon Jun 19 13:06:53 2006 -0600
@@ -1408,7 +1408,10 @@ vcpu_get_domain_bundle(VCPU* vcpu, REGS*
 vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
 {
        UINT64 gpip;// guest pseudo phyiscal ip
-
+       unsigned long vaddr;
+       struct page_info* page;
+
+again:
 #if 0
        // Currently xen doesn't track psr.it bits.
        // it assumes always psr.it = 1.
@@ -1471,8 +1474,22 @@ vcpu_get_domain_bundle(VCPU* vcpu, REGS*
                gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
                        (gip & ((1 << tr.ps) - 1));
        }
-
-       *bundle = *((IA64_BUNDLE*)__va(__gpa_to_mpa(vcpu->domain, gpip)));
+       
+       vaddr = domain_mpa_to_imva(vcpu->domain, gpip);
+       page = virt_to_page(vaddr);
+       if (get_page(page, vcpu->domain) == 0) {
+               if (page_get_owner(page) != vcpu->domain) {
+                       // This page might be a page granted by another
+                       // domain.
+                       panic_domain(regs,
+                                    "domain tries to execute foreign domain "
+                                    "page which might be mapped by grant "
+                                    "table.\n");
+               }
+               goto again;
+       }
+       *bundle = *((IA64_BUNDLE*)vaddr);
+       put_page(page);
        return 1;
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.