All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nadav Amit <namit@vmware.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	LKML <linux-kernel@vger.kernel.org>,
	Ingo Molnar <mingo@redhat.com>, X86 ML <x86@kernel.org>,
	Arnd Bergmann <arnd@arndb.de>,
	linux-arch <linux-arch@vger.kernel.org>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Jiri Kosina <jkosina@suse.cz>, Andy Lutomirski <luto@kernel.org>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Kees Cook <keescook@chromium.org>
Subject: Re: [PATCH v2 0/6] x86/alternatives: text_poke() fixes
Date: Thu, 6 Sep 2018 17:01:25 +0000	[thread overview]
Message-ID: <6703CD9F-2D84-4449-A423-A4DC24677673@vmware.com> (raw)
In-Reply-To: <20180906101641.GG24142@hirez.programming.kicks-ass.net>

at 3:16 AM, Peter Zijlstra <peterz@infradead.org> wrote:

> On Thu, Sep 06, 2018 at 10:13:00AM +0200, Peter Zijlstra wrote:
>> No, you got it the first time. There are in fact more fixmap abusers;
>> see drivers/acpi/apei/ghes.c.  Also, as long as set_fixmap() allows
>> overwriting a _PAGE_PRESENT pte and has that dodgy
>> __flush_tlb_one_kernel() in it, the broken remains (and can return).
>> 
>> So we need to fix fixmap, to either disallow overwriting a _PAGE_PRESENT
>> pte, or to issue a full TLB invalidate.
>> 
>> Either fix will terminally break GHES, but that's OK, they've known
>> about this issue since 2015 and haven't cared, so I can't be bothered
>> about them.
> 
> In fact, the below seems to cure all woes..
> 
> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
> index b9d5e7c9ef43..00f1c9e4f0a3 100644
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -709,22 +709,25 @@ void *text_poke(void *addr, const void *opcode, size_t len)
> 		pages[1] = virt_to_page(addr + PAGE_SIZE);
> 	}
> 	BUG_ON(!pages[0]);
> -	local_irq_save(flags);
> +
> 	set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
> 	if (pages[1])
> 		set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
> +
> +	local_irq_save(flags);
> 	vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
> 	memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
> -	clear_fixmap(FIX_TEXT_POKE0);
> -	if (pages[1])
> -		clear_fixmap(FIX_TEXT_POKE1);
> -	local_flush_tlb();
> 	sync_core();
> 	/* Could also do a CLFLUSH here to speed up CPU recovery; but
> 	   that causes hangs on some VIA CPUs. */
> 	for (i = 0; i < len; i++)
> 		BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
> 	local_irq_restore(flags);
> +
> +	clear_fixmap(FIX_TEXT_POKE0);
> +	if (pages[1])
> +		clear_fixmap(FIX_TEXT_POKE1);
> +
> 	return addr;
> }
> 
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index dd519f372169..fd6af66bc400 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -260,14 +260,28 @@ static void __set_pte_vaddr(pud_t *pud, unsigned long vaddr, pte_t new_pte)
> {
> 	pmd_t *pmd = fill_pmd(pud, vaddr);
> 	pte_t *pte = fill_pte(pmd, vaddr);
> +	pte_t old_pte = *pte;
> 
> 	set_pte(pte, new_pte);
> 
> 	/*
> -	 * It's enough to flush this one mapping.
> -	 * (PGE mappings get flushed as well)
> +	 * If it was present and changes, we need to invalidate TLBs.
> 	 */
> -	__flush_tlb_one_kernel(vaddr);
> +	if (!(pte_present(old_pte) && !pte_same(old_pte, new_pte)))
> +		return;
> +
> +	if (WARN(irqs_disabled(), "broken set_fixmap(%d, %lx), was: %lx",
> +				(int)__virt_to_fix(vaddr),
> +				pte_val(new_pte), pte_val(old_pte))) {
> +		/*
> +		 * It is _NOT_ enough to flush just the local mapping;
> +		 * it might mostly work, but there is no guarantee a remote
> +		 * CPU didn't load this entry into its TLB.
> +		 */
> +		__flush_tlb_one_kernel(vaddr);
> +	} else {
> +		flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
> +	}
> }
> 
> void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t new_pte)
> diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
> index 52ae5438edeb..e3c415bdbfbf 100644
> --- a/drivers/acpi/apei/Kconfig
> +++ b/drivers/acpi/apei/Kconfig
> @@ -19,6 +19,7 @@ config ACPI_APEI
> 
> config ACPI_APEI_GHES
> 	bool "APEI Generic Hardware Error Source"
> +	depends on BROKEN if X86
> 	depends on ACPI_APEI
> 	select ACPI_HED
> 	select IRQ_WORK

Indeed, I missed these other instances that use the fixmap.

I’ll give your patch a try once my server goes back online. I was (and still
am) worried that interrupts would be disabled when __set_pte_vaddr() is
called, which would make the fix more complicated.

In addition, there might be a couple of issues with your fix:

1. __set_pte_vaddr() is not used exclusive by set_fixmap(). This means
the warning might be wrong, but also means that these code patches (Xen’s
set_pte_mfn(), CPU-entry-area setup) needs to be checked. And as you said
before, someone might use this function for other purposes as well.

2. Printing the virtual address can break KASLR.

3. The WARN() can introduce some overhead since checking if IRQs are
disabled takes considerably long time. Perhaps VM_WARN() or something is
better. I realize this code-path is not on the hot-path though...

4. I guess flush_tlb_kernel_range() should also have something like
VM_WARN_ON(irqs_disabled()), just as an additional general sanity check.

Let me know if you want me to make these changes and include your patch in
the set.

Regards,
Nadav


  reply	other threads:[~2018-09-06 17:01 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-02 17:32 [PATCH v2 0/6] x86/alternatives: text_poke() fixes Nadav Amit
2018-09-02 17:32 ` Nadav Amit
2018-09-02 17:32 ` [PATCH v2 1/6] Fix "x86/alternatives: Lockdep-enforce text_mutex in text_poke*()" Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-06 19:40   ` Peter Zijlstra
2018-09-06 19:42     ` Nadav Amit
2018-09-06 19:53       ` Peter Zijlstra
2018-09-06 19:58         ` Nadav Amit
2018-09-06 20:25           ` Peter Zijlstra
2018-09-06 20:57             ` Nadav Amit
2018-09-06 21:41               ` Peter Zijlstra
2018-09-02 17:32 ` [PATCH v2 2/6] x86/mm: temporary mm struct Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-02 17:32 ` [PATCH v2 3/6] fork: provide a function for copying init_mm Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-02 17:32 ` [PATCH v2 4/6] x86/alternatives: initializing temporary mm for patching Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-06  9:01   ` Peter Zijlstra
2018-09-07 20:52     ` Nadav Amit
2018-09-02 17:32 ` [PATCH v2 5/6] x86/alternatives: use temporary mm for text poking Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-02 17:32 ` [PATCH v2 6/6] x86/alternatives: remove text_poke() return value Nadav Amit
2018-09-02 17:32   ` Nadav Amit
2018-09-05 18:56 ` [PATCH v2 0/6] x86/alternatives: text_poke() fixes Peter Zijlstra
2018-09-05 19:02   ` Nadav Amit
2018-09-05 19:10     ` Nadav Amit
2018-09-06  8:13       ` Peter Zijlstra
2018-09-06  8:42         ` Peter Zijlstra
2018-09-06  9:18         ` Peter Zijlstra
2018-09-06 10:16         ` Peter Zijlstra
2018-09-06 17:01           ` Nadav Amit [this message]
2018-09-06 17:17             ` Peter Zijlstra
2018-09-06 17:58               ` Nadav Amit
2018-09-06 18:09                 ` Andy Lutomirski
2018-09-06 18:31                   ` Peter Zijlstra
2018-09-06 18:38                     ` Nadav Amit
2018-09-06 19:19                       ` Peter Zijlstra
2018-09-06 17:23             ` Peter Zijlstra

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=6703CD9F-2D84-4449-A423-A4DC24677673@vmware.com \
    --to=namit@vmware.com \
    --cc=arnd@arndb.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=jkosina@suse.cz \
    --cc=keescook@chromium.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.