commit b4772cf849f05d5ceab079b4e88497dd1b990acd Author: Andy Lutomirski Date: Mon Jul 27 20:20:55 2015 -0700 x86/xen: Unmap aliases in xen_alloc_ldt and xen_free_ldt The xen_free_ldt change fixes an OOPS in the new modify_ldt implementation. I think the xen_alloc_ldt change should be necessary, too, but I can't seem to trigger any failures without it, which I find surprising. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Andy Lutomirski diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0b95c9b8283f..100a2e2294af 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -512,6 +513,10 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) for(i = 0; i < entries; i += entries_per_page) set_aliased_prot(ldt + i, PAGE_KERNEL_RO); + + /* If there are stray aliases, the LDT won't work. */ + if (is_vmalloc_addr(ldt)) + vm_unmap_aliases(); } static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) @@ -519,6 +524,13 @@ static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; + /* + * If there are stray aliases, hypervisor will fail the hypercalls, + * causing us to OOPS. + */ + if (is_vmalloc_addr(ldt)) + vm_unmap_aliases(); + for(i = 0; i < entries; i += entries_per_page) set_aliased_prot(ldt + i, PAGE_KERNEL); } diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c index c27adfc9ae72..fba5bc133aa2 100644 --- a/tools/testing/selftests/x86/ldt_gdt.c +++ b/tools/testing/selftests/x86/ldt_gdt.c @@ -204,6 +204,10 @@ static void do_simple_tests(void) }; install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB); + desc.entry_number = 8191; + install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB); + desc.entry_number = 0; + desc.limit_in_pages = 1; install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB | AR_G);