On Wed, 11 Dec 2019 12:43:37 +1100 Daniel Axtens <d...@axtens.net> wrote:
> If a process page-faults trying to write beyond the end of its > stack, we attempt to grow the stack. > > However, if the kernel attempts to write beyond the end of a > process's stack, it takes a bad fault. This can occur when the > kernel is trying to set up a signal frame. > > Permit the kernel to grow a process's stack. The same general > limits as to how and when the stack can be grown apply: the kernel > code still passes through expand_stack(), so anything that goes > beyond e.g. the rlimit should still be blocked. Thanks Daniel. Looks good from a function perspective. danielgb@ozrom2:~$ gcc -g -Wall -O stactest.c danielgb@ozrom2:~$ ./a.out 1240000 & [1] 4223 danielgb@ozrom2:~$ cat /proc/$(pidof a.out)/maps | grep stack ^[[3~7ffff14d0000-7ffff1600000 rw-p 00000000 00:00 0 [stack] danielgb@ozrom2:~$ kill -USR1 %1 danielgb@ozrom2:~$ signal delivered, stack base 0x7ffff1600000 top 0x7ffff14d1427 (1240025 used) [1]+ Done ./a.out 1240000 danielgb@ozrom2:~$ ./a.out 1241000 & [1] 4227 danielgb@ozrom2:~$ kill -USR1 %1 danielgb@ozrom2:~$ signal delivered, stack base 0x7fffff630000 top 0x7fffff501057 (1241001 used) [1]+ Done ./a.out 1241000 danielgb@ozrom2:~$ uname -a Linux ozrom2 5.5.0-rc1-00001-g83ab444248c1 #1 SMP Wed Dec 11 17:01:50 AEDT 2019 ppc64le ppc64le ppc64le GNU/Linux Tested-by: Daniel Black <dan...@linux.ibm.com> > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=205183 > Reported-by: Tom Lane <t...@sss.pgh.pa.us> > Cc: Daniel Black <dan...@linux.ibm.com> > Signed-off-by: Daniel Axtens <d...@axtens.net> > --- > arch/powerpc/mm/fault.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c > index b5047f9b5dec..00183731ea22 100644 > --- a/arch/powerpc/mm/fault.c > +++ b/arch/powerpc/mm/fault.c > @@ -287,7 +287,17 @@ static bool bad_stack_expansion(struct pt_regs *regs, > unsigned long address, > if (!res) > return !store_updates_sp(inst); > *must_retry = true; > + } else if ((flags & FAULT_FLAG_WRITE) && > + !(flags & FAULT_FLAG_USER)) { > + /* > + * the kernel can also attempt to write beyond the end > + * of a process's stack - for example setting up a > + * signal frame. We assume this is valid, subject to > + * the checks in expand_stack() later. > + */ > + return false; > } > + > return true; > } > return false;