All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christophe LEROY <christophe.leroy@c-s.fr>
To: Michael Neuling <mikey@neuling.org>, mpe@ellerman.id.au
Cc: linuxppc-dev@lists.ozlabs.org,
	"Nicholas Piggin" <npiggin@gmail.com>,
	paulus@ozlabs.org, "Haren Myneni" <haren@linux.vnet.ibm.com>,
	"Michal Suchánek" <msuchanek@suse.de>
Subject: Re: [PATCH v2] powerpc: Avoid code patching freed init sections
Date: Wed, 12 Sep 2018 08:23:29 +0200	[thread overview]
Message-ID: <0922624b-6c6f-1afd-a9e2-cde5a9a8a1e4@c-s.fr> (raw)
In-Reply-To: <20180912052058.10062-1-mikey@neuling.org>



Le 12/09/2018 à 07:20, Michael Neuling a écrit :
> This stops us from doing code patching in init sections after they've
> been freed.
> 
> In this chain:
>    kvm_guest_init() ->
>      kvm_use_magic_page() ->
>        fault_in_pages_readable() ->
> 	 __get_user() ->
> 	   __get_user_nocheck() ->
> 	     barrier_nospec();
> 
> We have a code patching location at barrier_nospec() and
> kvm_guest_init() is an init function. This whole chain gets inlined,
> so when we free the init section (hence kvm_guest_init()), this code
> goes away and hence should no longer be patched.
> 
> We seen this as userspace memory corruption when using a memory
> checker while doing partition migration testing on powervm (this
> starts the code patching post migration via
> /sys/kernel/mobility/migration). In theory, it could also happen when
> using /sys/kernel/debug/powerpc/barrier_nospec.
> 
> With this patch there is a small change of a race if we code patch
> between the init section being freed and setting SYSTEM_RUNNING (in
> kernel_init()) but that seems like an impractical time and small
> window for any code patching to occur.
> 
> cc: stable@vger.kernel.org # 4.13+
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> 
> ---
> For stable I've marked this as v4.13+ since that's when we refactored
> code-patching.c but it could go back even further than that. In
> reality though, I think we can only hit this since the first
> spectre/meltdown changes.
> 
> v2:
>    Print when we skip an address
> ---
>   arch/powerpc/lib/code-patching.c | 22 ++++++++++++++++++++++
>   1 file changed, 22 insertions(+)
> 
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index 850f3b8f4d..68254e7f17 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -23,11 +23,33 @@
>   #include <asm/code-patching.h>
>   #include <asm/setup.h>
>   
> +

This blank line is not needed

> +static inline bool in_init_section(unsigned int *patch_addr)
> +{
> +	if (patch_addr < (unsigned int *)__init_begin)
> +		return false;
> +	if (patch_addr >= (unsigned int *)__init_end)
> +		return false;
> +	return true;
> +}

Can we use the existing function init_section_contains() instead of this 
new function ?

> +
> +static inline bool init_freed(void)
> +{
> +	return (system_state >= SYSTEM_RUNNING);
> +}
> +

I would call this function differently, for instance init_is_finished(), 
because as you mentionned it doesn't exactly mean that init memory is freed.

>   static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
>   			       unsigned int *patch_addr)
>   {
>   	int err;
>   
> +	/* Make sure we aren't patching a freed init section */
> +	if (in_init_section(patch_addr) && init_freed()) {

The test must be done on exec_addr, not on patch_addr, as patch_addr is 
the address where the instruction as been remapped RW for allowing its 
modification.

Also I think it should be tested the other way round, because the 
init_freed() is a simpler test which will be false most of the time once 
the system is running so it should be checked first.

> +		printk(KERN_DEBUG "Skipping init section patching addr: 0x%lx\n",

Maybe use pr_debug() instead.

> +			(unsigned long)patch_addr);

Please align second line as per Codying style.

> +		return 0;
> +	}
> +
>   	__put_user_size(instr, patch_addr, 4, err);
>   	if (err)
>   		return err;
> 

I think it would be better to put this verification in 
patch_instruction() instead, to avoid RW mapping/unmapping the 
instruction to patch when we are not going to do the patching.

Christophe

  reply	other threads:[~2018-09-12  6:23 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-12  5:20 [PATCH v2] powerpc: Avoid code patching freed init sections Michael Neuling
2018-09-12  6:23 ` Christophe LEROY [this message]
2018-09-13  0:36   ` Michael Neuling
2018-09-13  1:21     ` Tyrel Datwyler
2018-09-13  5:38       ` Christophe LEROY
2018-09-13  5:48         ` Michael Neuling
2018-09-13  5:45     ` Christophe LEROY

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=0922624b-6c6f-1afd-a9e2-cde5a9a8a1e4@c-s.fr \
    --to=christophe.leroy@c-s.fr \
    --cc=haren@linux.vnet.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mikey@neuling.org \
    --cc=mpe@ellerman.id.au \
    --cc=msuchanek@suse.de \
    --cc=npiggin@gmail.com \
    --cc=paulus@ozlabs.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.