diff options
Diffstat (limited to 'main/xen/xsa58-4.2.patch')
-rw-r--r-- | main/xen/xsa58-4.2.patch | 129 |
1 files changed, 0 insertions, 129 deletions
diff --git a/main/xen/xsa58-4.2.patch b/main/xen/xsa58-4.2.patch deleted file mode 100644 index 1ea3aaa97d..0000000000 --- a/main/xen/xsa58-4.2.patch +++ /dev/null @@ -1,129 +0,0 @@ -x86: fix page refcount handling in page table pin error path - -In the original patch 7 of the series addressing XSA-45 I mistakenly -took the addition of the call to get_page_light() in alloc_page_type() -to cover two decrements that would happen: One for the PGT_partial bit -that is getting set along with the call, and the other for the page -reference the caller hold (and would be dropping on its error path). -But of course the additional page reference is tied to the PGT_partial -bit, and hence any caller of a function that may leave -->arch.old_guest_table non-NULL for error cleanup purposes has to make -sure a respective page reference gets retained. - -Similar issues were then also spotted elsewhere: In effect all callers -of get_page_type_preemptible() need to deal with errors in similar -ways. To make sure error handling can work this way without leaking -page references, a respective assertion gets added to that function. - -This is CVE-2013-1432 / XSA-58. - -Reported-by: Andrew Cooper <andrew.cooper3@citrix.com> -Signed-off-by: Jan Beulich <jbeulich@suse.com> -Tested-by: Andrew Cooper <andrew.cooper3@citrix.com> -Reviewed-by: Tim Deegan <tim@xen.org> - ---- a/xen/arch/x86/domain.c -+++ b/xen/arch/x86/domain.c -@@ -941,6 +941,10 @@ int arch_set_info_guest( - if ( v->vcpu_id == 0 ) - d->vm_assist = c(vm_assist); - -+ rc = put_old_guest_table(current); -+ if ( rc ) -+ return rc; -+ - if ( !compat ) - rc = (int)set_gdt(v, c.nat->gdt_frames, c.nat->gdt_ents); - #ifdef CONFIG_COMPAT -@@ -980,18 +984,24 @@ int arch_set_info_guest( - } - else - { -- /* -- * Since v->arch.guest_table{,_user} are both NULL, this effectively -- * is just a call to put_old_guest_table(). -- */ - if ( !compat ) -- rc = vcpu_destroy_pagetables(v); -+ rc = put_old_guest_table(v); - if ( !rc ) - rc = get_page_type_preemptible(cr3_page, - !compat ? PGT_root_page_table - : PGT_l3_page_table); -- if ( rc == -EINTR ) -+ switch ( rc ) -+ { -+ case -EINTR: - rc = -EAGAIN; -+ case -EAGAIN: -+ case 0: -+ break; -+ default: -+ if ( cr3_page == current->arch.old_guest_table ) -+ cr3_page = NULL; -+ break; -+ } - } - if ( rc ) - /* handled below */; -@@ -1018,6 +1028,11 @@ int arch_set_info_guest( - pagetable_get_page(v->arch.guest_table); - v->arch.guest_table = pagetable_null(); - break; -+ default: -+ if ( cr3_page == current->arch.old_guest_table ) -+ cr3_page = NULL; -+ case 0: -+ break; - } - } - if ( !rc ) ---- a/xen/arch/x86/mm.c -+++ b/xen/arch/x86/mm.c -@@ -718,7 +718,8 @@ static int get_page_and_type_from_pagenr - get_page_type_preemptible(page, type) : - (get_page_type(page, type) ? 0 : -EINVAL)); - -- if ( unlikely(rc) && partial >= 0 ) -+ if ( unlikely(rc) && partial >= 0 && -+ (!preemptible || page != current->arch.old_guest_table) ) - put_page(page); - - return rc; -@@ -2638,6 +2639,7 @@ int put_page_type_preemptible(struct pag - - int get_page_type_preemptible(struct page_info *page, unsigned long type) - { -+ ASSERT(!current->arch.old_guest_table); - return __get_page_type(page, type, 1); - } - -@@ -2848,7 +2850,7 @@ static void put_superpage(unsigned long - - #endif - --static int put_old_guest_table(struct vcpu *v) -+int put_old_guest_table(struct vcpu *v) - { - int rc; - -@@ -3253,7 +3255,8 @@ long do_mmuext_op( - rc = -EAGAIN; - else if ( rc != -EAGAIN ) - MEM_LOG("Error while pinning mfn %lx", page_to_mfn(page)); -- put_page(page); -+ if ( page != curr->arch.old_guest_table ) -+ put_page(page); - break; - } - ---- a/xen/include/asm-x86/mm.h -+++ b/xen/include/asm-x86/mm.h -@@ -374,6 +374,7 @@ void put_page_type(struct page_info *pag - int get_page_type(struct page_info *page, unsigned long type); - int put_page_type_preemptible(struct page_info *page); - int get_page_type_preemptible(struct page_info *page, unsigned long type); -+int put_old_guest_table(struct vcpu *); - int get_page_from_l1e( - l1_pgentry_t l1e, struct domain *l1e_owner, struct domain *pg_owner); - void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner); |