[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 4/4] x86: switch default mapping attributes to non-executable
On 18/05/15 13:47, Jan Beulich wrote: > Only a very limited subset of mappings need to be done as executable > ones; in particular the direct mapping should not be executable to > limit the damage attackers can cause by exploiting security relevant > bugs. > > The EFI change at once includes an adjustment to set NX only when > supported by the hardware. > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/xen/arch/x86/domain.c > +++ b/xen/arch/x86/domain.c > @@ -293,7 +293,7 @@ struct vcpu_guest_context *alloc_vcpu_gu > free_vcpu_guest_context(NULL); > return NULL; > } > - __set_fixmap(idx - i, page_to_mfn(pg), __PAGE_HYPERVISOR); > + __set_fixmap(idx - i, page_to_mfn(pg), __PAGE_HYPERVISOR_RW); > per_cpu(vgc_pages[i], cpu) = pg; > } > return (void *)fix_to_virt(idx); > --- a/xen/arch/x86/domain_page.c > +++ b/xen/arch/x86/domain_page.c > @@ -160,7 +160,7 @@ void *map_domain_page(unsigned long mfn) > > spin_unlock(&dcache->lock); > > - l1e_write(&MAPCACHE_L1ENT(idx), l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); > + l1e_write(&MAPCACHE_L1ENT(idx), l1e_from_pfn(mfn, __PAGE_HYPERVISOR_RW)); > > out: > local_irq_restore(flags); > --- a/xen/arch/x86/mm.c > +++ b/xen/arch/x86/mm.c > @@ -4416,7 +4416,7 @@ long set_gdt(struct vcpu *v, > for ( i = 0; i < nr_pages; i++ ) > { > v->arch.pv_vcpu.gdt_frames[i] = frames[i]; > - l1e_write(&pl1e[i], l1e_from_pfn(frames[i], __PAGE_HYPERVISOR)); > + l1e_write(&pl1e[i], l1e_from_pfn(frames[i], __PAGE_HYPERVISOR_RW)); > } > > xfree(pfns); > @@ -6004,7 +6004,7 @@ int create_perdomain_mapping(struct doma > if ( !IS_NIL(ppg) ) > *ppg++ = pg; > l1tab[l1_table_offset(va)] = > - l1e_from_page(pg, __PAGE_HYPERVISOR | _PAGE_AVAIL0); > + l1e_from_page(pg, __PAGE_HYPERVISOR_RW | _PAGE_AVAIL0); > l2e_add_flags(*pl2e, _PAGE_AVAIL0); > } > else > @@ -6133,7 +6133,7 @@ void memguard_init(void) > (unsigned long)__va(start), > start >> PAGE_SHIFT, > (__pa(&_end) + PAGE_SIZE - 1 - start) >> PAGE_SHIFT, > - __PAGE_HYPERVISOR|MAP_SMALL_PAGES); > + __PAGE_HYPERVISOR_RW|MAP_SMALL_PAGES); > BUG_ON(start != xen_phys_start); > map_pages_to_xen( > XEN_VIRT_START, > @@ -6146,7 +6146,7 @@ static void __memguard_change_range(void > { > unsigned long _p = (unsigned long)p; > unsigned long _l = (unsigned long)l; > - unsigned int flags = __PAGE_HYPERVISOR | MAP_SMALL_PAGES; > + unsigned int flags = __PAGE_HYPERVISOR_RW | MAP_SMALL_PAGES; > > /* Ensure we are dealing with a page-aligned whole number of pages. */ > ASSERT((_p&~PAGE_MASK) == 0); > --- a/xen/arch/x86/setup.c > +++ b/xen/arch/x86/setup.c > @@ -900,7 +900,7 @@ void __init noreturn __start_xen(unsigne > /* The only data mappings to be relocated are in the Xen area. */ > pl2e = __va(__pa(l2_xenmap)); > *pl2e++ = l2e_from_pfn(xen_phys_start >> PAGE_SHIFT, > - PAGE_HYPERVISOR | _PAGE_PSE); > + PAGE_HYPERVISOR_RWX | _PAGE_PSE); > for ( i = 1; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ ) > { > if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ) > @@ -1087,7 +1087,7 @@ void __init noreturn __start_xen(unsigne > /* This range must not be passed to the boot allocator and > * must also not be mapped with _PAGE_GLOBAL. */ > map_pages_to_xen((unsigned long)__va(map_e), PFN_DOWN(map_e), > - PFN_DOWN(e - map_e), __PAGE_HYPERVISOR); > + PFN_DOWN(e - map_e), __PAGE_HYPERVISOR_RW); > } > if ( s < map_s ) > { > --- a/xen/arch/x86/x86_64/mm.c > +++ b/xen/arch/x86/x86_64/mm.c > @@ -895,6 +895,33 @@ void __init subarch_init_memory(void) > share_xen_page_with_privileged_guests(page, XENSHARE_readonly); > } > } > + > + /* Mark low 16Mb of direct map NX if hardware supports it. */ > + if ( !cpu_has_nx ) > + return; > + > + v = DIRECTMAP_VIRT_START + (1UL << 20); What about 0-1MB ? > + l3e = l4e_to_l3e(idle_pg_table[l4_table_offset(v)])[l3_table_offset(v)]; > + ASSERT(l3e_get_flags(l3e) & _PAGE_PRESENT); > + do { > + l2e = l3e_to_l2e(l3e)[l2_table_offset(v)]; > + ASSERT(l2e_get_flags(l2e) & _PAGE_PRESENT); > + if ( l2e_get_flags(l2e) & _PAGE_PSE ) > + { > + l2e_add_flags(l2e, _PAGE_NX_BIT); > + l3e_to_l2e(l3e)[l2_table_offset(v)] = l2e; > + v += 1 << L2_PAGETABLE_SHIFT; > + } > + else > + { > + l1_pgentry_t l1e = l2e_to_l1e(l2e)[l1_table_offset(v)]; > + > + ASSERT(l1e_get_flags(l1e) & _PAGE_PRESENT); > + l1e_add_flags(l1e, _PAGE_NX_BIT); > + l2e_to_l1e(l2e)[l1_table_offset(v)] = l1e; > + v += 1 << L1_PAGETABLE_SHIFT; > + } > + } while ( v < DIRECTMAP_VIRT_START + (16UL << 20) ); How about just setting l3e.nx and leaving all lower tables alone? > } > > long subarch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) > @@ -1359,7 +1386,7 @@ int memory_add(unsigned long spfn, unsig > if ( i < spfn ) > i = spfn; > ret = map_pages_to_xen((unsigned long)mfn_to_virt(i), i, > - epfn - i, __PAGE_HYPERVISOR); > + epfn - i, __PAGE_HYPERVISOR_RW); > if ( ret ) > return ret; > } > --- a/xen/common/efi/boot.c > +++ b/xen/common/efi/boot.c > @@ -1162,7 +1162,7 @@ void __init efi_init_memory(void) > EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; > u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; > unsigned long smfn, emfn; > - unsigned int prot = PAGE_HYPERVISOR; > + unsigned int prot = PAGE_HYPERVISOR_RWX; > > printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64 > " type=%u attr=%016" PRIx64 "\n", > @@ -1195,7 +1195,7 @@ void __init efi_init_memory(void) > if ( desc->Attribute & EFI_MEMORY_WP ) > prot &= _PAGE_RW; > if ( desc->Attribute & EFI_MEMORY_XP ) > - prot |= _PAGE_NX_BIT; > + prot |= _PAGE_NX; > > if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) && > !(smfn & pfn_hole_mask) && > --- a/xen/include/asm-x86/page.h > +++ b/xen/include/asm-x86/page.h > @@ -303,7 +303,8 @@ void paging_init(void); > #define _PAGE_AVAIL1 _AC(0x400,U) > #define _PAGE_AVAIL2 _AC(0x800,U) > #define _PAGE_AVAIL _AC(0xE00,U) > -#define _PAGE_PSE_PAT _AC(0x1000,U) > +#define _PAGE_PSE_PAT _AC(0x1000,U) > +#define _PAGE_NX (cpu_has_nx ? _PAGE_NX_BIT : 0) > /* non-architectural flags */ > #define _PAGE_PAGED 0x2000U > #define _PAGE_SHARED 0x4000U > @@ -320,6 +321,9 @@ void paging_init(void); > #define _PAGE_GNTTAB 0 > #endif > > +#define __PAGE_HYPERVISOR_RO (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NX) > +#define __PAGE_HYPERVISOR_RW (__PAGE_HYPERVISOR_RO | \ > + _PAGE_DIRTY | _PAGE_RW) > #define __PAGE_HYPERVISOR_RX (_PAGE_PRESENT | _PAGE_ACCESSED) > #define __PAGE_HYPERVISOR (__PAGE_HYPERVISOR_RX | \ > _PAGE_DIRTY | _PAGE_RW) > --- a/xen/include/asm-x86/x86_64/page.h > +++ b/xen/include/asm-x86/x86_64/page.h > @@ -147,9 +147,20 @@ typedef l4_pgentry_t root_pgentry_t; > */ > #define _PAGE_GUEST_KERNEL (1U<<12) > > -#define PAGE_HYPERVISOR (__PAGE_HYPERVISOR | _PAGE_GLOBAL) > +#define PAGE_HYPERVISOR_RO (__PAGE_HYPERVISOR_RO | _PAGE_GLOBAL) > +#define PAGE_HYPERVISOR_RW (__PAGE_HYPERVISOR_RW | _PAGE_GLOBAL) > #define PAGE_HYPERVISOR_RX (__PAGE_HYPERVISOR_RX | _PAGE_GLOBAL) > -#define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL) > +#define PAGE_HYPERVISOR_RWX (__PAGE_HYPERVISOR | _PAGE_GLOBAL) > + > +#ifdef __ASSEMBLY__ > +/* Dependency on NX being available can't be expressed. */ > +# define PAGE_HYPERVISOR PAGE_HYPERVISOR_RWX > +# define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL) > +#else > +# define PAGE_HYPERVISOR PAGE_HYPERVISOR_RW > +# define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | \ > + _PAGE_GLOBAL | _PAGE_NX) > +#endif This patch is clearly an improvement, so my comments can possibly be deferred to subsequent patches. After boot, I can't think of a legitimate reason for Xen to have a RWX mapping. As such, leaving __PAGE_HYPERVISOR around constitutes a risk that RWX mappings will be used. It would be nice if we could remove all constants (which aren't BOOT_*) which could lead to accidental use of RWX mappings on NX-enabled hardware. I think we also want a warning on boot if we find NX unavailable. The only 64bit capable CPUs which do not support NX are now 11 years old, and I don't expect many of those to be running Xen these days. However, given that "disable NX" is a common BIOS option for compatibility reasons, we should press people to alter their settings if possible. ~Andrew > > #endif /* __X86_64_PAGE_H__ */ > > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |