In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);current->thread.used_spe=true;}elseif(current->thread.used_spe)-memset(current->thread.evr,0,ELF_NEVRREG*sizeof(u32));+memset(¤t->thread.spe,0,sizeof(current->thread.spe));/* Always get SPEFSCR back */unsafe_get_user(current->thread.spefscr,(u32__user*)&sr->mc_vregs+ELF_NEVRREG,failed);
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2021-08-20 07:49:51
Kees Cook [off-list ref] writes:
quoted hunk
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);
This makes me nervous, because the ABI is that we copy ELF_NEVRREG *
sizeof(u32) bytes, not whatever sizeof(current->thread.spe) happens to
be.
ie. if we use sizeof an inadvertent change to the fields in
thread_struct could change how many bytes we copy out to userspace,
which would be an ABI break.
And that's not that hard to do, because it's not at all obvious that the
size and layout of fields in thread_struct affects the user ABI.
At the same time we don't want to copy the right number of bytes but
the wrong content, so from that point of view using sizeof is good :)
The way we handle it in ptrace is to have BUILD_BUG_ON()s to verify that
things match up, so maybe we should do that here too.
ie. add:
BUILD_BUG_ON(sizeof(current->thread.spe) == ELF_NEVRREG * sizeof(u32));
Not sure if you are happy doing that as part of this patch. I can always
do it later if not.
cheers
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);
This makes me nervous, because the ABI is that we copy ELF_NEVRREG *
sizeof(u32) bytes, not whatever sizeof(current->thread.spe) happens to
be.
ie. if we use sizeof an inadvertent change to the fields in
thread_struct could change how many bytes we copy out to userspace,
which would be an ABI break.
And that's not that hard to do, because it's not at all obvious that the
size and layout of fields in thread_struct affects the user ABI.
At the same time we don't want to copy the right number of bytes but
the wrong content, so from that point of view using sizeof is good :)
The way we handle it in ptrace is to have BUILD_BUG_ON()s to verify that
things match up, so maybe we should do that here too.
ie. add:
BUILD_BUG_ON(sizeof(current->thread.spe) == ELF_NEVRREG * sizeof(u32));
You mean != I guess ?
Not sure if you are happy doing that as part of this patch. I can always
do it later if not.
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2021-08-20 12:14:04
Christophe Leroy [off-list ref] writes:
Le 20/08/2021 à 09:49, Michael Ellerman a écrit :
quoted
Kees Cook [off-list ref] writes:
quoted
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);
This makes me nervous, because the ABI is that we copy ELF_NEVRREG *
sizeof(u32) bytes, not whatever sizeof(current->thread.spe) happens to
be.
ie. if we use sizeof an inadvertent change to the fields in
thread_struct could change how many bytes we copy out to userspace,
which would be an ABI break.
And that's not that hard to do, because it's not at all obvious that the
size and layout of fields in thread_struct affects the user ABI.
At the same time we don't want to copy the right number of bytes but
the wrong content, so from that point of view using sizeof is good :)
The way we handle it in ptrace is to have BUILD_BUG_ON()s to verify that
things match up, so maybe we should do that here too.
ie. add:
BUILD_BUG_ON(sizeof(current->thread.spe) == ELF_NEVRREG * sizeof(u32));
On Fri, Aug 20, 2021 at 05:49:35PM +1000, Michael Ellerman wrote:
Kees Cook [off-list ref] writes:
quoted
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);
This makes me nervous, because the ABI is that we copy ELF_NEVRREG *
sizeof(u32) bytes, not whatever sizeof(current->thread.spe) happens to
be.
ie. if we use sizeof an inadvertent change to the fields in
thread_struct could change how many bytes we copy out to userspace,
which would be an ABI break.
And that's not that hard to do, because it's not at all obvious that the
size and layout of fields in thread_struct affects the user ABI.
At the same time we don't want to copy the right number of bytes but
the wrong content, so from that point of view using sizeof is good :)
The way we handle it in ptrace is to have BUILD_BUG_ON()s to verify that
things match up, so maybe we should do that here too.
ie. add:
BUILD_BUG_ON(sizeof(current->thread.spe) == ELF_NEVRREG * sizeof(u32));
Not sure if you are happy doing that as part of this patch. I can always
do it later if not.
Sounds good to me; I did that in a few other cases in the series where
the relationships between things seemed tenuous. :) I'll add this (as
!=) in v3.
Thanks!
--
Kees Cook
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2021-08-23 04:56:15
Kees Cook [off-list ref] writes:
On Fri, Aug 20, 2021 at 05:49:35PM +1000, Michael Ellerman wrote:
quoted
Kees Cook [off-list ref] writes:
quoted
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memset(), avoid intentionally writing across
neighboring fields.
Add a struct_group() for the spe registers so that memset() can correctly reason
about the size:
In function 'fortify_memset_chk',
inlined from 'restore_user_regs.part.0' at arch/powerpc/kernel/signal_32.c:539:3:
quoted
quoted
include/linux/fortify-string.h:195:4: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
@@ -191,8 +191,10 @@ struct thread_struct {intused_vsr;/* set if process has used VSX */#endif /* CONFIG_VSX */#ifdef CONFIG_SPE-unsignedlongevr[32];/* upper 32-bits of SPE regs */-u64acc;/* Accumulator */+struct_group(spe,+unsignedlongevr[32];/* upper 32-bits of SPE regs */+u64acc;/* Accumulator */+);unsignedlongspefscr;/* SPE & eFP status */unsignedlongspefscr_last;/* SPEFSCR value on last prctlcallortrapreturn*/
@@ -532,11 +532,11 @@ static long restore_user_regs(struct pt_regs *regs,regs_set_return_msr(regs,regs->msr&~MSR_SPE);if(msr&MSR_SPE){/* restore spe registers from the stack */-unsafe_copy_from_user(current->thread.evr,&sr->mc_vregs,-ELF_NEVRREG*sizeof(u32),failed);+unsafe_copy_from_user(¤t->thread.spe,&sr->mc_vregs,+sizeof(current->thread.spe),failed);
This makes me nervous, because the ABI is that we copy ELF_NEVRREG *
sizeof(u32) bytes, not whatever sizeof(current->thread.spe) happens to
be.
ie. if we use sizeof an inadvertent change to the fields in
thread_struct could change how many bytes we copy out to userspace,
which would be an ABI break.
And that's not that hard to do, because it's not at all obvious that the
size and layout of fields in thread_struct affects the user ABI.
At the same time we don't want to copy the right number of bytes but
the wrong content, so from that point of view using sizeof is good :)
The way we handle it in ptrace is to have BUILD_BUG_ON()s to verify that
things match up, so maybe we should do that here too.
ie. add:
BUILD_BUG_ON(sizeof(current->thread.spe) == ELF_NEVRREG * sizeof(u32));
Not sure if you are happy doing that as part of this patch. I can always
do it later if not.
Sounds good to me; I did that in a few other cases in the series where
the relationships between things seemed tenuous. :) I'll add this (as
!=) in v3.