All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc: Fix initrd corruption with relative jump labels
@ 2021-06-14 13:14 Michael Ellerman
  2021-06-14 15:57 ` Greg Kurz
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Michael Ellerman @ 2021-06-14 13:14 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: r.bolshakov, a.kovaleva, groug, dja

Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
us to using relative jump labels. That involves changing the code,
target and key members in struct jump_entry to be relative to the
address of the jump_entry, rather than absolute addresses.

We have two static inlines that create a struct jump_entry,
arch_static_branch() and arch_static_branch_jump(), as well as an asm
macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
tracing code.

Unfortunately we missed updating the key to be a relative reference in
ARCH_STATIC_BRANCH.

That causes a pseries kernel to have a handful of jump_entry structs
with bad key values. Instead of being a relative reference they instead
hold the full address of the key.

However the code doesn't expect that, it still adds the key value to the
address of the jump_entry (see jump_entry_key()) expecting to get a
pointer to a key somewhere in kernel data.

The table of jump_entry structs sits in rodata, which comes after the
kernel text. In a typical build this will be somewhere around 15MB. The
address of the key will be somewhere in data, typically around 20MB.
Adding the two values together gets us a pointer somewhere around 45MB.

We then call static_key_set_entries() with that bad pointer and modify
some members of the struct static_key we think we are pointing at.

A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
corrupt the kernel itself. However if we're booting with an initrd,
depending on the size and exact location of the initrd, we can corrupt
the initrd. Depending on how exactly we corrupt the initrd it can either
cause the system to not boot, or just corrupt one of the files in the
initrd.

The fix is simply to make the key value relative to the jump_entry
struct in the ARCH_STATIC_BRANCH macro.

Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
Reported-by: Greg Kurz <groug@kaod.org>
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/jump_label.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 2d5c6bec2b4f..93ce3ec25387 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 1098:	nop;					\
 	.pushsection __jump_table, "aw";	\
 	.long 1098b - ., LABEL - .;		\
-	FTR_ENTRY_LONG KEY;			\
+	FTR_ENTRY_LONG KEY - .;			\
 	.popsection
 #endif
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
@ 2021-06-14 15:57 ` Greg Kurz
  2021-06-15 10:51   ` Greg Kurz
  2021-06-15  1:15 ` Daniel Axtens
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Greg Kurz @ 2021-06-14 15:57 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: a.kovaleva, r.bolshakov, linuxppc-dev, dja

On Mon, 14 Jun 2021 23:14:40 +1000
Michael Ellerman <mpe@ellerman.id.au> wrote:

> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> us to using relative jump labels. That involves changing the code,
> target and key members in struct jump_entry to be relative to the
> address of the jump_entry, rather than absolute addresses.
> 
> We have two static inlines that create a struct jump_entry,
> arch_static_branch() and arch_static_branch_jump(), as well as an asm
> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> tracing code.
> 
> Unfortunately we missed updating the key to be a relative reference in
> ARCH_STATIC_BRANCH.
> 
> That causes a pseries kernel to have a handful of jump_entry structs
> with bad key values. Instead of being a relative reference they instead
> hold the full address of the key.
> 
> However the code doesn't expect that, it still adds the key value to the
> address of the jump_entry (see jump_entry_key()) expecting to get a
> pointer to a key somewhere in kernel data.
> 
> The table of jump_entry structs sits in rodata, which comes after the
> kernel text. In a typical build this will be somewhere around 15MB. The
> address of the key will be somewhere in data, typically around 20MB.
> Adding the two values together gets us a pointer somewhere around 45MB.
> 
> We then call static_key_set_entries() with that bad pointer and modify
> some members of the struct static_key we think we are pointing at.
> 
> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
> corrupt the kernel itself. However if we're booting with an initrd,
> depending on the size and exact location of the initrd, we can corrupt
> the initrd. Depending on how exactly we corrupt the initrd it can either
> cause the system to not boot, or just corrupt one of the files in the
> initrd.
> 
> The fix is simply to make the key value relative to the jump_entry
> struct in the ARCH_STATIC_BRANCH macro.
> 
> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Reported-by: Greg Kurz <groug@kaod.org>
> Reported-by: Daniel Axtens <dja@axtens.net>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---

Great thanks for debugging this issue ! I'll try it out tomorrow morning.

Cheers,

--
Greg

>  arch/powerpc/include/asm/jump_label.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
> index 2d5c6bec2b4f..93ce3ec25387 100644
> --- a/arch/powerpc/include/asm/jump_label.h
> +++ b/arch/powerpc/include/asm/jump_label.h
> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
>  1098:	nop;					\
>  	.pushsection __jump_table, "aw";	\
>  	.long 1098b - ., LABEL - .;		\
> -	FTR_ENTRY_LONG KEY;			\
> +	FTR_ENTRY_LONG KEY - .;			\
>  	.popsection
>  #endif
>  


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
  2021-06-14 15:57 ` Greg Kurz
@ 2021-06-15  1:15 ` Daniel Axtens
  2021-06-15 13:25 ` Anastasia Kovaleva
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-06-15  1:15 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: r.bolshakov, a.kovaleva, groug

Hi Michael,

> The fix is simply to make the key value relative to the jump_entry
> struct in the ARCH_STATIC_BRANCH macro.

This fixes the boot issues I observed. Thank you very much!!

Tested-by: Daniel Axtens <dja@axtens.net>

Kind regards,
Daniel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 15:57 ` Greg Kurz
@ 2021-06-15 10:51   ` Greg Kurz
  0 siblings, 0 replies; 10+ messages in thread
From: Greg Kurz @ 2021-06-15 10:51 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, r.bolshakov, a.kovaleva, dja

On Mon, 14 Jun 2021 17:57:40 +0200
Greg Kurz <groug@kaod.org> wrote:

> On Mon, 14 Jun 2021 23:14:40 +1000
> Michael Ellerman <mpe@ellerman.id.au> wrote:
> 
> > Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> > us to using relative jump labels. That involves changing the code,
> > target and key members in struct jump_entry to be relative to the
> > address of the jump_entry, rather than absolute addresses.
> > 
> > We have two static inlines that create a struct jump_entry,
> > arch_static_branch() and arch_static_branch_jump(), as well as an asm
> > macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> > tracing code.
> > 
> > Unfortunately we missed updating the key to be a relative reference in
> > ARCH_STATIC_BRANCH.
> > 
> > That causes a pseries kernel to have a handful of jump_entry structs
> > with bad key values. Instead of being a relative reference they instead
> > hold the full address of the key.
> > 
> > However the code doesn't expect that, it still adds the key value to the
> > address of the jump_entry (see jump_entry_key()) expecting to get a
> > pointer to a key somewhere in kernel data.
> > 
> > The table of jump_entry structs sits in rodata, which comes after the
> > kernel text. In a typical build this will be somewhere around 15MB. The
> > address of the key will be somewhere in data, typically around 20MB.
> > Adding the two values together gets us a pointer somewhere around 45MB.
> > 
> > We then call static_key_set_entries() with that bad pointer and modify
> > some members of the struct static_key we think we are pointing at.
> > 
> > A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
> > corrupt the kernel itself. However if we're booting with an initrd,
> > depending on the size and exact location of the initrd, we can corrupt
> > the initrd. Depending on how exactly we corrupt the initrd it can either
> > cause the system to not boot, or just corrupt one of the files in the
> > initrd.
> > 
> > The fix is simply to make the key value relative to the jump_entry
> > struct in the ARCH_STATIC_BRANCH macro.
> > 
> > Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
> > Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
> > Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
> > Reported-by: Greg Kurz <groug@kaod.org>
> > Reported-by: Daniel Axtens <dja@axtens.net>
> > Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> > ---
> 
> Great thanks for debugging this issue ! I'll try it out tomorrow morning.
> 

This fixes the issue. Great thanks again :)

Tested-by: Greg Kurz <groug@kaod.org>

> Cheers,
> 
> --
> Greg
> 
> >  arch/powerpc/include/asm/jump_label.h | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
> > index 2d5c6bec2b4f..93ce3ec25387 100644
> > --- a/arch/powerpc/include/asm/jump_label.h
> > +++ b/arch/powerpc/include/asm/jump_label.h
> > @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
> >  1098:	nop;					\
> >  	.pushsection __jump_table, "aw";	\
> >  	.long 1098b - ., LABEL - .;		\
> > -	FTR_ENTRY_LONG KEY;			\
> > +	FTR_ENTRY_LONG KEY - .;			\
> >  	.popsection
> >  #endif
> >  
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
  2021-06-14 15:57 ` Greg Kurz
  2021-06-15  1:15 ` Daniel Axtens
@ 2021-06-15 13:25 ` Anastasia Kovaleva
  2021-06-15 13:40   ` Roman Bolshakov
  2021-06-18  3:50 ` Michael Ellerman
  4 siblings, 0 replies; 10+ messages in thread
From: Anastasia Kovaleva @ 2021-06-15 13:25 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Roman Bolshakov, linuxppc-dev, groug, dja


> On 14 Jun 2021, at 16:14, Michael Ellerman <mpe@ellerman.id.au> wrote:
> 
> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> us to using relative jump labels. That involves changing the code,
> target and key members in struct jump_entry to be relative to the
> address of the jump_entry, rather than absolute addresses.
> 
> We have two static inlines that create a struct jump_entry,
> arch_static_branch() and arch_static_branch_jump(), as well as an asm
> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> tracing code.
> 
> Unfortunately we missed updating the key to be a relative reference in
> ARCH_STATIC_BRANCH.
> 
> That causes a pseries kernel to have a handful of jump_entry structs
> with bad key values. Instead of being a relative reference they instead
> hold the full address of the key.
> 
> However the code doesn't expect that, it still adds the key value to the
> address of the jump_entry (see jump_entry_key()) expecting to get a
> pointer to a key somewhere in kernel data.
> 
> The table of jump_entry structs sits in rodata, which comes after the
> kernel text. In a typical build this will be somewhere around 15MB. The
> address of the key will be somewhere in data, typically around 20MB.
> Adding the two values together gets us a pointer somewhere around 45MB.
> 
> We then call static_key_set_entries() with that bad pointer and modify
> some members of the struct static_key we think we are pointing at.
> 
> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
> corrupt the kernel itself. However if we're booting with an initrd,
> depending on the size and exact location of the initrd, we can corrupt
> the initrd. Depending on how exactly we corrupt the initrd it can either
> cause the system to not boot, or just corrupt one of the files in the
> initrd.
> 
> The fix is simply to make the key value relative to the jump_entry
> struct in the ARCH_STATIC_BRANCH macro.
> 
> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Reported-by: Greg Kurz <groug@kaod.org>
> Reported-by: Daniel Axtens <dja@axtens.net>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
> arch/powerpc/include/asm/jump_label.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
> index 2d5c6bec2b4f..93ce3ec25387 100644
> --- a/arch/powerpc/include/asm/jump_label.h
> +++ b/arch/powerpc/include/asm/jump_label.h
> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
> 1098:	nop;					\
> 	.pushsection __jump_table, "aw";	\
> 	.long 1098b - ., LABEL - .;		\
> -	FTR_ENTRY_LONG KEY;			\
> +	FTR_ENTRY_LONG KEY - .;			\
> 	.popsection
> #endif
> 
> -- 
> 2.25.1
> 

This fixes the issue. Thank you a lot!

Tested-by: Anastasia Kovaleva <a.kovaleva@yadro.com>

Thanks,
Anastasia


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
@ 2021-06-15 13:40   ` Roman Bolshakov
  2021-06-15  1:15 ` Daniel Axtens
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Roman Bolshakov @ 2021-06-15 13:40 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: linuxppc-dev, dja, christophe.leroy, a.kovaleva, groug,
	Linus Torvalds, linux-kernel

On Mon, Jun 14, 2021 at 11:14:40PM +1000, Michael Ellerman wrote:
> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> us to using relative jump labels. That involves changing the code,
> target and key members in struct jump_entry to be relative to the
> address of the jump_entry, rather than absolute addresses.
> 
> We have two static inlines that create a struct jump_entry,
> arch_static_branch() and arch_static_branch_jump(), as well as an asm
> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> tracing code.
> 
> Unfortunately we missed updating the key to be a relative reference in
> ARCH_STATIC_BRANCH.
> 
> That causes a pseries kernel to have a handful of jump_entry structs
> with bad key values. Instead of being a relative reference they instead
> hold the full address of the key.
> 
> However the code doesn't expect that, it still adds the key value to the
> address of the jump_entry (see jump_entry_key()) expecting to get a
> pointer to a key somewhere in kernel data.
> 
> The table of jump_entry structs sits in rodata, which comes after the
> kernel text. In a typical build this will be somewhere around 15MB. The
> address of the key will be somewhere in data, typically around 20MB.
> Adding the two values together gets us a pointer somewhere around 45MB.
> 
> We then call static_key_set_entries() with that bad pointer and modify
> some members of the struct static_key we think we are pointing at.
> 
> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
> corrupt the kernel itself. However if we're booting with an initrd,
> depending on the size and exact location of the initrd, we can corrupt
> the initrd. Depending on how exactly we corrupt the initrd it can either
> cause the system to not boot, or just corrupt one of the files in the
> initrd.
> 
> The fix is simply to make the key value relative to the jump_entry
> struct in the ARCH_STATIC_BRANCH macro.
> 
> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Reported-by: Greg Kurz <groug@kaod.org>
> Reported-by: Daniel Axtens <dja@axtens.net>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
>  arch/powerpc/include/asm/jump_label.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
> index 2d5c6bec2b4f..93ce3ec25387 100644
> --- a/arch/powerpc/include/asm/jump_label.h
> +++ b/arch/powerpc/include/asm/jump_label.h
> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
>  1098:	nop;					\
>  	.pushsection __jump_table, "aw";	\
>  	.long 1098b - ., LABEL - .;		\
> -	FTR_ENTRY_LONG KEY;			\
> +	FTR_ENTRY_LONG KEY - .;			\
>  	.popsection
>  #endif
>  
> -- 
> 2.25.1
> 

Thanks for fixing the issue, Michael.

Perhaps the fix should go to v5.13-rc7 if Linus plans to do it. It'd be
good to avoid broken initrd on pseries guests in the release.

Regards,
Roman

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
@ 2021-06-15 13:40   ` Roman Bolshakov
  0 siblings, 0 replies; 10+ messages in thread
From: Roman Bolshakov @ 2021-06-15 13:40 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Linus Torvalds, linuxppc-dev, groug, a.kovaleva, linux-kernel, dja

On Mon, Jun 14, 2021 at 11:14:40PM +1000, Michael Ellerman wrote:
> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> us to using relative jump labels. That involves changing the code,
> target and key members in struct jump_entry to be relative to the
> address of the jump_entry, rather than absolute addresses.
> 
> We have two static inlines that create a struct jump_entry,
> arch_static_branch() and arch_static_branch_jump(), as well as an asm
> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> tracing code.
> 
> Unfortunately we missed updating the key to be a relative reference in
> ARCH_STATIC_BRANCH.
> 
> That causes a pseries kernel to have a handful of jump_entry structs
> with bad key values. Instead of being a relative reference they instead
> hold the full address of the key.
> 
> However the code doesn't expect that, it still adds the key value to the
> address of the jump_entry (see jump_entry_key()) expecting to get a
> pointer to a key somewhere in kernel data.
> 
> The table of jump_entry structs sits in rodata, which comes after the
> kernel text. In a typical build this will be somewhere around 15MB. The
> address of the key will be somewhere in data, typically around 20MB.
> Adding the two values together gets us a pointer somewhere around 45MB.
> 
> We then call static_key_set_entries() with that bad pointer and modify
> some members of the struct static_key we think we are pointing at.
> 
> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
> corrupt the kernel itself. However if we're booting with an initrd,
> depending on the size and exact location of the initrd, we can corrupt
> the initrd. Depending on how exactly we corrupt the initrd it can either
> cause the system to not boot, or just corrupt one of the files in the
> initrd.
> 
> The fix is simply to make the key value relative to the jump_entry
> struct in the ARCH_STATIC_BRANCH macro.
> 
> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Reported-by: Greg Kurz <groug@kaod.org>
> Reported-by: Daniel Axtens <dja@axtens.net>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
>  arch/powerpc/include/asm/jump_label.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
> index 2d5c6bec2b4f..93ce3ec25387 100644
> --- a/arch/powerpc/include/asm/jump_label.h
> +++ b/arch/powerpc/include/asm/jump_label.h
> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
>  1098:	nop;					\
>  	.pushsection __jump_table, "aw";	\
>  	.long 1098b - ., LABEL - .;		\
> -	FTR_ENTRY_LONG KEY;			\
> +	FTR_ENTRY_LONG KEY - .;			\
>  	.popsection
>  #endif
>  
> -- 
> 2.25.1
> 

Thanks for fixing the issue, Michael.

Perhaps the fix should go to v5.13-rc7 if Linus plans to do it. It'd be
good to avoid broken initrd on pseries guests in the release.

Regards,
Roman

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-15 13:40   ` Roman Bolshakov
@ 2021-06-16  2:40     ` Michael Ellerman
  -1 siblings, 0 replies; 10+ messages in thread
From: Michael Ellerman @ 2021-06-16  2:40 UTC (permalink / raw)
  To: Roman Bolshakov
  Cc: linuxppc-dev, dja, christophe.leroy, a.kovaleva, groug,
	Linus Torvalds, linux-kernel

Roman Bolshakov <r.bolshakov@yadro.com> writes:
> On Mon, Jun 14, 2021 at 11:14:40PM +1000, Michael Ellerman wrote:
>> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
>> us to using relative jump labels. That involves changing the code,
>> target and key members in struct jump_entry to be relative to the
>> address of the jump_entry, rather than absolute addresses.
>> 
>> We have two static inlines that create a struct jump_entry,
>> arch_static_branch() and arch_static_branch_jump(), as well as an asm
>> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
>> tracing code.
>> 
>> Unfortunately we missed updating the key to be a relative reference in
>> ARCH_STATIC_BRANCH.
>> 
>> That causes a pseries kernel to have a handful of jump_entry structs
>> with bad key values. Instead of being a relative reference they instead
>> hold the full address of the key.
>> 
>> However the code doesn't expect that, it still adds the key value to the
>> address of the jump_entry (see jump_entry_key()) expecting to get a
>> pointer to a key somewhere in kernel data.
>> 
>> The table of jump_entry structs sits in rodata, which comes after the
>> kernel text. In a typical build this will be somewhere around 15MB. The
>> address of the key will be somewhere in data, typically around 20MB.
>> Adding the two values together gets us a pointer somewhere around 45MB.
>> 
>> We then call static_key_set_entries() with that bad pointer and modify
>> some members of the struct static_key we think we are pointing at.
>> 
>> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
>> corrupt the kernel itself. However if we're booting with an initrd,
>> depending on the size and exact location of the initrd, we can corrupt
>> the initrd. Depending on how exactly we corrupt the initrd it can either
>> cause the system to not boot, or just corrupt one of the files in the
>> initrd.
>> 
>> The fix is simply to make the key value relative to the jump_entry
>> struct in the ARCH_STATIC_BRANCH macro.
>> 
>> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
>> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
>> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
>> Reported-by: Greg Kurz <groug@kaod.org>
>> Reported-by: Daniel Axtens <dja@axtens.net>
>> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
>> ---
>>  arch/powerpc/include/asm/jump_label.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
>> index 2d5c6bec2b4f..93ce3ec25387 100644
>> --- a/arch/powerpc/include/asm/jump_label.h
>> +++ b/arch/powerpc/include/asm/jump_label.h
>> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
>>  1098:	nop;					\
>>  	.pushsection __jump_table, "aw";	\
>>  	.long 1098b - ., LABEL - .;		\
>> -	FTR_ENTRY_LONG KEY;			\
>> +	FTR_ENTRY_LONG KEY - .;			\
>>  	.popsection
>>  #endif
>>  
>> -- 
>> 2.25.1
>> 
>
> Thanks for fixing the issue, Michael.
>
> Perhaps the fix should go to v5.13-rc7 if Linus plans to do it. It'd be
> good to avoid broken initrd on pseries guests in the release.

Yes it's in my fixes branch and I'll ask Linus to pull that before the
next rc.

cheers

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
@ 2021-06-16  2:40     ` Michael Ellerman
  0 siblings, 0 replies; 10+ messages in thread
From: Michael Ellerman @ 2021-06-16  2:40 UTC (permalink / raw)
  To: Roman Bolshakov
  Cc: Linus Torvalds, linuxppc-dev, groug, a.kovaleva, linux-kernel, dja

Roman Bolshakov <r.bolshakov@yadro.com> writes:
> On Mon, Jun 14, 2021 at 11:14:40PM +1000, Michael Ellerman wrote:
>> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
>> us to using relative jump labels. That involves changing the code,
>> target and key members in struct jump_entry to be relative to the
>> address of the jump_entry, rather than absolute addresses.
>> 
>> We have two static inlines that create a struct jump_entry,
>> arch_static_branch() and arch_static_branch_jump(), as well as an asm
>> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
>> tracing code.
>> 
>> Unfortunately we missed updating the key to be a relative reference in
>> ARCH_STATIC_BRANCH.
>> 
>> That causes a pseries kernel to have a handful of jump_entry structs
>> with bad key values. Instead of being a relative reference they instead
>> hold the full address of the key.
>> 
>> However the code doesn't expect that, it still adds the key value to the
>> address of the jump_entry (see jump_entry_key()) expecting to get a
>> pointer to a key somewhere in kernel data.
>> 
>> The table of jump_entry structs sits in rodata, which comes after the
>> kernel text. In a typical build this will be somewhere around 15MB. The
>> address of the key will be somewhere in data, typically around 20MB.
>> Adding the two values together gets us a pointer somewhere around 45MB.
>> 
>> We then call static_key_set_entries() with that bad pointer and modify
>> some members of the struct static_key we think we are pointing at.
>> 
>> A pseries kernel is typically ~30MB in size, so writing to ~45MB won't
>> corrupt the kernel itself. However if we're booting with an initrd,
>> depending on the size and exact location of the initrd, we can corrupt
>> the initrd. Depending on how exactly we corrupt the initrd it can either
>> cause the system to not boot, or just corrupt one of the files in the
>> initrd.
>> 
>> The fix is simply to make the key value relative to the jump_entry
>> struct in the ARCH_STATIC_BRANCH macro.
>> 
>> Fixes: b0b3b2c78ec0 ("powerpc: Switch to relative jump labels")
>> Reported-by: Anastasia Kovaleva <a.kovaleva@yadro.com>
>> Reported-by: Roman Bolshakov <r.bolshakov@yadro.com>
>> Reported-by: Greg Kurz <groug@kaod.org>
>> Reported-by: Daniel Axtens <dja@axtens.net>
>> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
>> ---
>>  arch/powerpc/include/asm/jump_label.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
>> index 2d5c6bec2b4f..93ce3ec25387 100644
>> --- a/arch/powerpc/include/asm/jump_label.h
>> +++ b/arch/powerpc/include/asm/jump_label.h
>> @@ -50,7 +50,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
>>  1098:	nop;					\
>>  	.pushsection __jump_table, "aw";	\
>>  	.long 1098b - ., LABEL - .;		\
>> -	FTR_ENTRY_LONG KEY;			\
>> +	FTR_ENTRY_LONG KEY - .;			\
>>  	.popsection
>>  #endif
>>  
>> -- 
>> 2.25.1
>> 
>
> Thanks for fixing the issue, Michael.
>
> Perhaps the fix should go to v5.13-rc7 if Linus plans to do it. It'd be
> good to avoid broken initrd on pseries guests in the release.

Yes it's in my fixes branch and I'll ask Linus to pull that before the
next rc.

cheers

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] powerpc: Fix initrd corruption with relative jump labels
  2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
                   ` (3 preceding siblings ...)
  2021-06-15 13:40   ` Roman Bolshakov
@ 2021-06-18  3:50 ` Michael Ellerman
  4 siblings, 0 replies; 10+ messages in thread
From: Michael Ellerman @ 2021-06-18  3:50 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: r.bolshakov, a.kovaleva, groug, dja

On Mon, 14 Jun 2021 23:14:40 +1000, Michael Ellerman wrote:
> Commit b0b3b2c78ec0 ("powerpc: Switch to relative jump labels") switched
> us to using relative jump labels. That involves changing the code,
> target and key members in struct jump_entry to be relative to the
> address of the jump_entry, rather than absolute addresses.
> 
> We have two static inlines that create a struct jump_entry,
> arch_static_branch() and arch_static_branch_jump(), as well as an asm
> macro ARCH_STATIC_BRANCH, which is used by the pseries-only hypervisor
> tracing code.
> 
> [...]

Applied to powerpc/fixes.

[1/1] powerpc: Fix initrd corruption with relative jump labels
      https://git.kernel.org/powerpc/c/478036c4cd1a16e613a2f883d79c03cf187faacb

cheers

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-06-18  3:51 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-14 13:14 [PATCH] powerpc: Fix initrd corruption with relative jump labels Michael Ellerman
2021-06-14 15:57 ` Greg Kurz
2021-06-15 10:51   ` Greg Kurz
2021-06-15  1:15 ` Daniel Axtens
2021-06-15 13:25 ` Anastasia Kovaleva
2021-06-15 13:40 ` Roman Bolshakov
2021-06-15 13:40   ` Roman Bolshakov
2021-06-16  2:40   ` Michael Ellerman
2021-06-16  2:40     ` Michael Ellerman
2021-06-18  3:50 ` Michael Ellerman

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.