head 1.2; access; symbols pkgsrc-2020Q2:1.1.0.24 pkgsrc-2020Q2-base:1.1 pkgsrc-2020Q1:1.1.0.20 pkgsrc-2020Q1-base:1.1 pkgsrc-2019Q4:1.1.0.22 pkgsrc-2019Q4-base:1.1 pkgsrc-2019Q3:1.1.0.18 pkgsrc-2019Q3-base:1.1 pkgsrc-2019Q2:1.1.0.16 pkgsrc-2019Q2-base:1.1 pkgsrc-2019Q1:1.1.0.14 pkgsrc-2019Q1-base:1.1 pkgsrc-2018Q4:1.1.0.12 pkgsrc-2018Q4-base:1.1 pkgsrc-2018Q3:1.1.0.10 pkgsrc-2018Q3-base:1.1 pkgsrc-2018Q2:1.1.0.8 pkgsrc-2018Q2-base:1.1 pkgsrc-2018Q1:1.1.0.6 pkgsrc-2018Q1-base:1.1 pkgsrc-2017Q4:1.1.0.4 pkgsrc-2017Q4-base:1.1 pkgsrc-2017Q3:1.1.0.2; locks; strict; comment @# @; 1.2 date 2020.08.19.10.39.23; author bouyer; state dead; branches; next 1.1; commitid DGAMglRf0Jde6FkC; 1.1 date 2017.10.17.10.57.34; author bouyer; state Exp; branches 1.1.2.1; next ; commitid Op7VCttvsVltwobA; 1.1.2.1 date 2017.10.17.10.57.34; author bsiegert; state dead; branches; next 1.1.2.2; commitid hV2F1sd8zeL8jrbA; 1.1.2.2 date 2017.10.17.19.17.50; author bsiegert; state Exp; branches; next ; commitid hV2F1sd8zeL8jrbA; desc @@ 1.2 log @Remove xenkernel and xentools packages older than 4.11. They're not maintained anymore upstream, and don't build on supported NetBSD releases. @ text @$NetBSD: patch-XSA234,v 1.1 2017/10/17 10:57:34 bouyer Exp $ From: Jan Beulich Subject: gnttab: also validate PTE permissions upon destroy/replace In order for PTE handling to match up with the reference counting done by common code, presence and writability of grant mapping PTEs must also be taken into account; validating just the frame number is not enough. This is in particular relevant if a guest fiddles with grant PTEs via non-grant hypercalls. Note that the flags being passed to replace_grant_host_mapping() already happen to be those of the existing mapping, so no new function parameter is needed. This is XSA-234. Reported-by: Andrew Cooper Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- xen/arch/x86/mm.c.orig +++ xen/arch/x86/mm.c @@@@ -3930,7 +3930,8 @@@@ static int create_grant_pte_mapping( } static int destroy_grant_pte_mapping( - uint64_t addr, unsigned long frame, struct domain *d) + uint64_t addr, unsigned long frame, unsigned int grant_pte_flags, + struct domain *d) { int rc = GNTST_okay; void *va; @@@@ -3976,16 +3977,27 @@@@ static int destroy_grant_pte_mapping( ol1e = *(l1_pgentry_t *)va; - /* Check that the virtual address supplied is actually mapped to frame. */ - if ( unlikely(l1e_get_pfn(ol1e) != frame) ) + /* + * Check that the PTE supplied actually maps frame (with appropriate + * permissions). + */ + if ( unlikely(l1e_get_pfn(ol1e) != frame) || + unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + (_PAGE_PRESENT | _PAGE_RW)) ) { page_unlock(page); - MEM_LOG("PTE entry %lx for address %"PRIx64" doesn't match frame %lx", - (unsigned long)l1e_get_intpte(ol1e), addr, frame); + MEM_LOG("PTE %"PRIpte" at %"PRIx64" doesn't match grant (%"PRIpte")", + l1e_get_intpte(ol1e), addr, + l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags))); rc = GNTST_general_error; goto failed; } + if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) ) + MEM_LOG("PTE flags %x at %"PRIx64" don't match grant (%x)\n", + l1e_get_flags(ol1e), addr, grant_pte_flags); + /* Delete pagetable entry. */ if ( unlikely(!UPDATE_ENTRY (l1, @@@@ -3994,7 +4006,7 @@@@ static int destroy_grant_pte_mapping( 0)) ) { page_unlock(page); - MEM_LOG("Cannot delete PTE entry at %p", va); + MEM_LOG("Cannot delete PTE entry at %"PRIx64, addr); rc = GNTST_general_error; goto failed; } @@@@ -4062,7 +4074,8 @@@@ static int create_grant_va_mapping( } static int replace_grant_va_mapping( - unsigned long addr, unsigned long frame, l1_pgentry_t nl1e, struct vcpu *v) + unsigned long addr, unsigned long frame, unsigned int grant_pte_flags, + l1_pgentry_t nl1e, struct vcpu *v) { l1_pgentry_t *pl1e, ol1e; unsigned long gl1mfn; @@@@ -4098,19 +4111,30 @@@@ static int replace_grant_va_mapping( ol1e = *pl1e; - /* Check that the virtual address supplied is actually mapped to frame. */ - if ( unlikely(l1e_get_pfn(ol1e) != frame) ) - { - MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx", - l1e_get_pfn(ol1e), addr, frame); + /* + * Check that the virtual address supplied is actually mapped to frame + * (with appropriate permissions). + */ + if ( unlikely(l1e_get_pfn(ol1e) != frame) || + unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + (_PAGE_PRESENT | _PAGE_RW)) ) + { + MEM_LOG("PTE %"PRIpte" for %lx doesn't match grant (%"PRIpte")", + l1e_get_intpte(ol1e), addr, + l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags))); rc = GNTST_general_error; goto unlock_and_out; } + if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) ) + MEM_LOG("PTE flags %x for %"PRIx64" don't match grant (%x)", + l1e_get_flags(ol1e), addr, grant_pte_flags); + /* Delete pagetable entry. */ if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) ) { - MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); + MEM_LOG("Cannot delete PTE entry for %"PRIx64, addr); rc = GNTST_general_error; goto unlock_and_out; } @@@@ -4124,9 +4148,11 @@@@ static int replace_grant_va_mapping( } static int destroy_grant_va_mapping( - unsigned long addr, unsigned long frame, struct vcpu *v) + unsigned long addr, unsigned long frame, unsigned int grant_pte_flags, + struct vcpu *v) { - return replace_grant_va_mapping(addr, frame, l1e_empty(), v); + return replace_grant_va_mapping(addr, frame, grant_pte_flags, + l1e_empty(), v); } static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame, @@@@ -4219,21 +4245,40 @@@@ int replace_grant_host_mapping( unsigned long gl1mfn; struct page_info *l1pg; int rc; + unsigned int grant_pte_flags; if ( paging_mode_external(current->domain) ) return replace_grant_p2m_mapping(addr, frame, new_addr, flags); + grant_pte_flags = + _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_GNTTAB | _PAGE_NX; + + if ( flags & GNTMAP_application_map ) + grant_pte_flags |= _PAGE_USER; + if ( !(flags & GNTMAP_readonly) ) + grant_pte_flags |= _PAGE_RW; + /* + * On top of the explicit settings done by create_grant_host_mapping() + * also open-code relevant parts of adjust_guest_l1e(). Don't mirror + * available and cachability flags, though. + */ + if ( !is_pv_32bit_domain(curr->domain) ) + grant_pte_flags |= (grant_pte_flags & _PAGE_USER) + ? _PAGE_GLOBAL + : _PAGE_GUEST_KERNEL | _PAGE_USER; + if ( flags & GNTMAP_contains_pte ) { if ( !new_addr ) - return destroy_grant_pte_mapping(addr, frame, curr->domain); + return destroy_grant_pte_mapping(addr, frame, grant_pte_flags, + curr->domain); MEM_LOG("Unsupported grant table operation"); return GNTST_general_error; } if ( !new_addr ) - return destroy_grant_va_mapping(addr, frame, curr); + return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr); pl1e = guest_map_l1e(curr, new_addr, &gl1mfn); if ( !pl1e ) @@@@ -4281,7 +4326,7 @@@@ int replace_grant_host_mapping( put_page(l1pg); guest_unmap_l1e(curr, pl1e); - rc = replace_grant_va_mapping(addr, frame, ol1e, curr); + rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr); if ( rc && !paging_mode_refcounts(curr->domain) ) put_page_from_l1e(ol1e, curr->domain); @ 1.1 log @Update xen*46 to 4.6.6, including fixes up to XSA244. changes since Xen 4.6.5: mostly bug fixes, including security fixes for XSA206, XSA211 to XSA244. PKGREVISION set to 1 to account for the fact that it's not a stock Xen 4.6.6. Note that, unlike upstream, pv-linear-pt defaults to true, so that NetBSD PV guests (including dom0) will continue to boot without changes to boot.cfg @ text @d1 1 a1 1 $NetBSD: $ @ 1.1.2.1 log @file patch-XSA234 was added on branch pkgsrc-2017Q3 on 2017-10-17 19:17:50 +0000 @ text @d1 187 @ 1.1.2.2 log @Pullup ticket #5580 - requested by bouyer sysutils/xenkernel46, sysutils/xentools46: security fix Revisions pulled up: - sysutils/xenkernel46/MESSAGE 1.2 - sysutils/xenkernel46/Makefile 1.14 - sysutils/xenkernel46/distinfo 1.10 - sysutils/xenkernel46/patches/patch-XSA-212 deleted - sysutils/xenkernel46/patches/patch-XSA226 1.1 - sysutils/xenkernel46/patches/patch-XSA227 1.1 - sysutils/xenkernel46/patches/patch-XSA228 1.1 - sysutils/xenkernel46/patches/patch-XSA230 1.1 - sysutils/xenkernel46/patches/patch-XSA231 1.1 - sysutils/xenkernel46/patches/patch-XSA232 1.1 - sysutils/xenkernel46/patches/patch-XSA234 1.1 - sysutils/xenkernel46/patches/patch-XSA237 1.1 - sysutils/xenkernel46/patches/patch-XSA238 1.1 - sysutils/xenkernel46/patches/patch-XSA239 1.1 - sysutils/xenkernel46/patches/patch-XSA240 1.1 - sysutils/xenkernel46/patches/patch-XSA241 1.1 - sysutils/xenkernel46/patches/patch-XSA242 1.1 - sysutils/xenkernel46/patches/patch-XSA243 1.1 - sysutils/xenkernel46/patches/patch-XSA244 1.1 - sysutils/xentools46/Makefile 1.21 - sysutils/xentools46/distinfo 1.9 - sysutils/xentools46/patches/patch-XSA-211-1 deleted - sysutils/xentools46/patches/patch-XSA-211-2 deleted - sysutils/xentools46/patches/patch-XSA228 1.1 - sysutils/xentools46/patches/patch-XSA233 1.1 - sysutils/xentools46/patches/patch-XSA240 1.1 - sysutils/xentools46/version.mk 1.3 --- Module Name: pkgsrc Committed By: bouyer Date: Tue Oct 17 10:57:35 UTC 2017 Modified Files: pkgsrc/sysutils/xenkernel46: MESSAGE Makefile distinfo pkgsrc/sysutils/xentools46: Makefile distinfo version.mk Added Files: pkgsrc/sysutils/xenkernel46/patches: patch-XSA226 patch-XSA227 patch-XSA228 patch-XSA230 patch-XSA231 patch-XSA232 patch-XSA234 patch-XSA237 patch-XSA238 patch-XSA239 patch-XSA240 patch-XSA241 patch-XSA242 patch-XSA243 patch-XSA244 pkgsrc/sysutils/xentools46/patches: patch-XSA228 patch-XSA233 patch-XSA240 Removed Files: pkgsrc/sysutils/xenkernel46/patches: patch-XSA-212 pkgsrc/sysutils/xentools46/patches: patch-XSA-211-1 patch-XSA-211-2 Log Message: Update xen*46 to 4.6.6, including fixes up to XSA244. changes since Xen 4.6.5: mostly bug fixes, including security fixes for XSA206, XSA211 to XSA244. PKGREVISION set to 1 to account for the fact that it's not a stock Xen 4.6.6. Note that, unlike upstream, pv-linear-pt defaults to true, so that NetBSD PV guests (including dom0) will continue to boot without changes to boot.cfg @ text @a0 187 $NetBSD: patch-XSA234,v 1.1 2017/10/17 10:57:34 bouyer Exp $ From: Jan Beulich Subject: gnttab: also validate PTE permissions upon destroy/replace In order for PTE handling to match up with the reference counting done by common code, presence and writability of grant mapping PTEs must also be taken into account; validating just the frame number is not enough. This is in particular relevant if a guest fiddles with grant PTEs via non-grant hypercalls. Note that the flags being passed to replace_grant_host_mapping() already happen to be those of the existing mapping, so no new function parameter is needed. This is XSA-234. Reported-by: Andrew Cooper Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- xen/arch/x86/mm.c.orig +++ xen/arch/x86/mm.c @@@@ -3930,7 +3930,8 @@@@ static int create_grant_pte_mapping( } static int destroy_grant_pte_mapping( - uint64_t addr, unsigned long frame, struct domain *d) + uint64_t addr, unsigned long frame, unsigned int grant_pte_flags, + struct domain *d) { int rc = GNTST_okay; void *va; @@@@ -3976,16 +3977,27 @@@@ static int destroy_grant_pte_mapping( ol1e = *(l1_pgentry_t *)va; - /* Check that the virtual address supplied is actually mapped to frame. */ - if ( unlikely(l1e_get_pfn(ol1e) != frame) ) + /* + * Check that the PTE supplied actually maps frame (with appropriate + * permissions). + */ + if ( unlikely(l1e_get_pfn(ol1e) != frame) || + unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + (_PAGE_PRESENT | _PAGE_RW)) ) { page_unlock(page); - MEM_LOG("PTE entry %lx for address %"PRIx64" doesn't match frame %lx", - (unsigned long)l1e_get_intpte(ol1e), addr, frame); + MEM_LOG("PTE %"PRIpte" at %"PRIx64" doesn't match grant (%"PRIpte")", + l1e_get_intpte(ol1e), addr, + l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags))); rc = GNTST_general_error; goto failed; } + if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) ) + MEM_LOG("PTE flags %x at %"PRIx64" don't match grant (%x)\n", + l1e_get_flags(ol1e), addr, grant_pte_flags); + /* Delete pagetable entry. */ if ( unlikely(!UPDATE_ENTRY (l1, @@@@ -3994,7 +4006,7 @@@@ static int destroy_grant_pte_mapping( 0)) ) { page_unlock(page); - MEM_LOG("Cannot delete PTE entry at %p", va); + MEM_LOG("Cannot delete PTE entry at %"PRIx64, addr); rc = GNTST_general_error; goto failed; } @@@@ -4062,7 +4074,8 @@@@ static int create_grant_va_mapping( } static int replace_grant_va_mapping( - unsigned long addr, unsigned long frame, l1_pgentry_t nl1e, struct vcpu *v) + unsigned long addr, unsigned long frame, unsigned int grant_pte_flags, + l1_pgentry_t nl1e, struct vcpu *v) { l1_pgentry_t *pl1e, ol1e; unsigned long gl1mfn; @@@@ -4098,19 +4111,30 @@@@ static int replace_grant_va_mapping( ol1e = *pl1e; - /* Check that the virtual address supplied is actually mapped to frame. */ - if ( unlikely(l1e_get_pfn(ol1e) != frame) ) - { - MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx", - l1e_get_pfn(ol1e), addr, frame); + /* + * Check that the virtual address supplied is actually mapped to frame + * (with appropriate permissions). + */ + if ( unlikely(l1e_get_pfn(ol1e) != frame) || + unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + (_PAGE_PRESENT | _PAGE_RW)) ) + { + MEM_LOG("PTE %"PRIpte" for %lx doesn't match grant (%"PRIpte")", + l1e_get_intpte(ol1e), addr, + l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags))); rc = GNTST_general_error; goto unlock_and_out; } + if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) & + ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) ) + MEM_LOG("PTE flags %x for %"PRIx64" don't match grant (%x)", + l1e_get_flags(ol1e), addr, grant_pte_flags); + /* Delete pagetable entry. */ if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) ) { - MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); + MEM_LOG("Cannot delete PTE entry for %"PRIx64, addr); rc = GNTST_general_error; goto unlock_and_out; } @@@@ -4124,9 +4148,11 @@@@ static int replace_grant_va_mapping( } static int destroy_grant_va_mapping( - unsigned long addr, unsigned long frame, struct vcpu *v) + unsigned long addr, unsigned long frame, unsigned int grant_pte_flags, + struct vcpu *v) { - return replace_grant_va_mapping(addr, frame, l1e_empty(), v); + return replace_grant_va_mapping(addr, frame, grant_pte_flags, + l1e_empty(), v); } static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame, @@@@ -4219,21 +4245,40 @@@@ int replace_grant_host_mapping( unsigned long gl1mfn; struct page_info *l1pg; int rc; + unsigned int grant_pte_flags; if ( paging_mode_external(current->domain) ) return replace_grant_p2m_mapping(addr, frame, new_addr, flags); + grant_pte_flags = + _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_GNTTAB | _PAGE_NX; + + if ( flags & GNTMAP_application_map ) + grant_pte_flags |= _PAGE_USER; + if ( !(flags & GNTMAP_readonly) ) + grant_pte_flags |= _PAGE_RW; + /* + * On top of the explicit settings done by create_grant_host_mapping() + * also open-code relevant parts of adjust_guest_l1e(). Don't mirror + * available and cachability flags, though. + */ + if ( !is_pv_32bit_domain(curr->domain) ) + grant_pte_flags |= (grant_pte_flags & _PAGE_USER) + ? _PAGE_GLOBAL + : _PAGE_GUEST_KERNEL | _PAGE_USER; + if ( flags & GNTMAP_contains_pte ) { if ( !new_addr ) - return destroy_grant_pte_mapping(addr, frame, curr->domain); + return destroy_grant_pte_mapping(addr, frame, grant_pte_flags, + curr->domain); MEM_LOG("Unsupported grant table operation"); return GNTST_general_error; } if ( !new_addr ) - return destroy_grant_va_mapping(addr, frame, curr); + return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr); pl1e = guest_map_l1e(curr, new_addr, &gl1mfn); if ( !pl1e ) @@@@ -4281,7 +4326,7 @@@@ int replace_grant_host_mapping( put_page(l1pg); guest_unmap_l1e(curr, pl1e); - rc = replace_grant_va_mapping(addr, frame, ol1e, curr); + rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr); if ( rc && !paging_mode_refcounts(curr->domain) ) put_page_from_l1e(ol1e, curr->domain); @