From: Andy Lutomirski <luto@kernel.org> To: X86 ML <x86@kernel.org>, Borislav Petkov <bp@alien8.de>, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org> Cc: Peter Zijlstra <peterz@infradead.org>, Steven Rostedt <rostedt@goodmis.org>, "security@kernel.org" <security@kernel.org>, Sasha Levin <sasha.levin@oracle.com>, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>, Boris Ostrovsky <boris.ostrovsky@oracle.com>, Andrew Cooper <andrew.cooper3@citrix.com>, Jan Beulich <jbeulich@suse.com>, xen-devel <xen-devel@lists.xen.org>, Andy Lutomirski <luto@kernel.org>, stable@vger.kernel.org, David Vrabel <dvrabel@cantab.net> Subject: [PATCH v6 1/4] x86/xen: Probe target addresses in set_aliased_prot before the hypercall Date: Thu, 30 Jul 2015 14:31:31 -0700 Message-ID: <0b0e55b995cda11e7829f140b833ef932fcabe3a.1438291540.git.luto@kernel.org> (raw) In-Reply-To: <cover.1438291540.git.luto@kernel.org> In-Reply-To: <cover.1438291540.git.luto@kernel.org> The update_va_mapping hypercall can fail if the VA isn't present in the guest's page tables. Under certain loads, this can result in an OOPS when the target address is in unpopulated vmap space. While we're at it, add comments to help explain what's going on. This isn't a great long-term fix. This code should probably be changed to use something like set_memory_ro. Cc: stable@vger.kernel.org Cc: Andrew Cooper <andrew.cooper3@citrix.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: David Vrabel <dvrabel@cantab.net> Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/xen/enlighten.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0b95c9b8283f..09f7fd6aa5c8 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -483,6 +483,7 @@ static void set_aliased_prot(void *v, pgprot_t prot) pte_t pte; unsigned long pfn; struct page *page; + unsigned char dummy; ptep = lookup_address((unsigned long)v, &level); BUG_ON(ptep == NULL); @@ -492,6 +493,32 @@ static void set_aliased_prot(void *v, pgprot_t prot) pte = pfn_pte(pfn, prot); + /* + * Careful: update_va_mapping will fail if the virtual address + * we're poking isn't populated in the page tables. We don't + * need to worry about the direct map (that's always in the page + * tables), but we need to be careful about vmap space. In + * particular, the top level page table can lazily propagate + * entries between processes, so if we've switched mms since we + * vmapped the target in the first place, we might not have the + * top-level page table entry populated. + * + * We disable preemption because we want the same mm active when + * we probe the target and when we issue the hypercall. We'll + * have the same nominal mm, but if we're a kernel thread, lazy + * mm dropping could change our pgd. + * + * Out of an abundance of caution, this uses __get_user to fault + * in the target address just in case there's some obscure case + * in which the target address isn't readable. + */ + + preempt_disable(); + + pagefault_disable(); /* Avoid warnings due to being atomic. */ + __get_user(dummy, (unsigned char __user __force *)v); + pagefault_enable(); + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) BUG(); @@ -503,6 +530,8 @@ static void set_aliased_prot(void *v, pgprot_t prot) BUG(); } else kmap_flush_unused(); + + preempt_enable(); } static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) @@ -510,6 +539,17 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; + /* + * We need to mark the all aliases of the LDT pages RO. We + * don't need to call vm_flush_aliases(), though, since that's + * only responsible for flushing aliases out the TLBs, not the + * page tables, and Xen will flush the TLB for us if needed. + * + * To avoid confusing future readers: none of this is necessary + * to load the LDT. The hypervisor only checks this when the + * LDT is faulted in due to subsequent descriptor access. + */ + for(i = 0; i < entries; i += entries_per_page) set_aliased_prot(ldt + i, PAGE_KERNEL_RO); } -- 2.4.3
next prev parent reply index Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-07-30 21:31 [PATCH v6 0/4] x86: modify_ldt improvement, test, and config option Andy Lutomirski 2015-07-30 21:31 ` Andy Lutomirski [this message] 2015-07-31 9:41 ` [Xen-devel] [PATCH v6 1/4] x86/xen: Probe target addresses in set_aliased_prot before the hypercall David Vrabel 2015-07-31 13:56 ` [tip:x86/asm] x86/xen: Probe target addresses in set_aliased_prot () " tip-bot for Andy Lutomirski 2015-07-30 21:31 ` [PATCH v6 2/4] x86/ldt: Make modify_ldt synchronous Andy Lutomirski 2015-07-30 22:50 ` Andrew Cooper 2015-07-31 3:15 ` Andy Lutomirski 2015-07-31 13:56 ` [tip:x86/asm] " tip-bot for Andy Lutomirski 2015-07-30 21:31 ` [PATCH v6 3/4] selftests/x86, x86/ldt: Add a selftest for modify_ldt Andy Lutomirski 2015-07-31 13:57 ` [tip:x86/asm] selftests/x86, x86/ldt: Add a selftest for modify_ldt() tip-bot for Andy Lutomirski 2015-07-30 21:31 ` [PATCH v6 4/4] x86/ldt: Make modify_ldt optional Andy Lutomirski 2015-07-31 13:49 ` Ingo Molnar 2015-07-31 14:02 ` [tip:x86/asm] x86/ldt: Make modify_ldt() optional tip-bot for Andy Lutomirski 2015-07-31 9:10 ` [PATCH v6 0/4] x86: modify_ldt improvement, test, and config option Andrew Cooper 2015-07-31 13:44 ` Boris Ostrovsky 2015-07-31 14:02 ` Andrew Cooper
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=0b0e55b995cda11e7829f140b833ef932fcabe3a.1438291540.git.luto@kernel.org \ --to=luto@kernel.org \ --cc=andrew.cooper3@citrix.com \ --cc=boris.ostrovsky@oracle.com \ --cc=bp@alien8.de \ --cc=dvrabel@cantab.net \ --cc=jbeulich@suse.com \ --cc=konrad.wilk@oracle.com \ --cc=linux-kernel@vger.kernel.org \ --cc=peterz@infradead.org \ --cc=rostedt@goodmis.org \ --cc=sasha.levin@oracle.com \ --cc=security@kernel.org \ --cc=stable@vger.kernel.org \ --cc=x86@kernel.org \ --cc=xen-devel@lists.xen.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
LKML Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git git clone --mirror https://lore.kernel.org/lkml/9 lkml/git/9.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \ linux-kernel@vger.kernel.org public-inbox-index lkml Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel AGPL code for this site: git clone https://public-inbox.org/public-inbox.git