Re: [PATCH] powerpc/lib: fix book3s/32 boot failure due to code patching

From: Michael Neuling
Date: Mon Oct 01 2018 - 19:19:56 EST


On Mon, 2018-10-01 at 12:21 +0000, Christophe Leroy wrote:
> Commit 51c3c62b58b3 ("powerpc: Avoid code patching freed init
> sections") accesses 'init_mem_is_free' flag too early, before the
> kernel is relocated. This provokes early boot failure (before the
> console is active).
>
> As it is not necessary to do this verification that early, this
> patch moves the test into patch_instruction() instead of
> __patch_instruction().
>
> This modification also has the advantage of avoiding unnecessary
> remappings.
>
> Fixes: 51c3c62b58b3 ("powerpc: Avoid code patching freed init sections")
> Signed-off-by: Christophe Leroy <christophe.leroy@xxxxxx>

Thanks

Acked-by: Michael Neuling <mikey@xxxxxxxxxxx>

The original patch was also marked for stable so we should do the same here.

Cc: stable@xxxxxxxxxxxxxxx # 4.13+

> ---
> arch/powerpc/lib/code-patching.c | 20 ++++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-
> patching.c
> index 6ae2777c220d..5ffee298745f 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -28,12 +28,6 @@ static int __patch_instruction(unsigned int *exec_addr,
> unsigned int instr,
> {
> int err;
>
> - /* Make sure we aren't patching a freed init section */
> - if (init_mem_is_free && init_section_contains(exec_addr, 4)) {
> - pr_debug("Skipping init section patching addr: 0x%px\n",
> exec_addr);
> - return 0;
> - }
> -
> __put_user_size(instr, patch_addr, 4, err);
> if (err)
> return err;
> @@ -148,7 +142,7 @@ static inline int unmap_patch_area(unsigned long addr)
> return 0;
> }
>
> -int patch_instruction(unsigned int *addr, unsigned int instr)
> +static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> {
> int err;
> unsigned int *patch_addr = NULL;
> @@ -188,12 +182,22 @@ int patch_instruction(unsigned int *addr, unsigned int
> instr)
> }
> #else /* !CONFIG_STRICT_KERNEL_RWX */
>
> -int patch_instruction(unsigned int *addr, unsigned int instr)
> +static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> {
> return raw_patch_instruction(addr, instr);
> }
>
> #endif /* CONFIG_STRICT_KERNEL_RWX */
> +
> +int patch_instruction(unsigned int *addr, unsigned int instr)
> +{
> + /* Make sure we aren't patching a freed init section */
> + if (init_mem_is_free && init_section_contains(addr, 4)) {
> + pr_debug("Skipping init section patching addr: 0x%px\n", addr);
> + return 0;
> + }
> + return do_patch_instruction(addr, instr);
> +}
> NOKPROBE_SYMBOL(patch_instruction);
>
> int patch_branch(unsigned int *addr, unsigned long target, int flags)