1 file changed, 19 insertions(+), 17 deletions(-) index dfcee3888b00..f58f1d574931 100644 --- b/kernel/signal.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff -puN kernel/signal.c~linux-sigaltstack kernel/signal.c --- a/kernel/signal.c~linux-sigaltstack 2021-12-19 16:50:41.411762535 -0800 +++ b/kernel/signal.c 2021-12-19 21:14:14.605399136 -0800 @@ -4161,7 +4161,6 @@ do_sigaltstack (const stack_t *ss, stack size_t min_ss_size) { struct task_struct *t = current; - int ret = 0; if (oss) { memset(oss, 0, sizeof(stack_t)); @@ -4181,8 +4180,15 @@ do_sigaltstack (const stack_t *ss, stack return -EPERM; ss_mode = ss_flags & ~SS_FLAG_BITS; - if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK && - ss_mode != 0)) + + if (ss_mode == SS_DISABLE) { + t->sas_ss_sp = 0; + t->sas_ss_size = 0; + t->sas_ss_flags = ss_flags; + return 0; + } + + if (unlikely(ss_mode != SS_ONSTACK && ss_mode != 0)) return -EINVAL; /* @@ -4194,24 +4200,25 @@ do_sigaltstack (const stack_t *ss, stack t->sas_ss_flags == ss_flags) return 0; + /* + * Lock out any changes to sigaltstack_size_valid() + * until the t->sas_ss_* changes are complete: + */ sigaltstack_lock(); - if (ss_mode == SS_DISABLE) { - ss_size = 0; - ss_sp = NULL; - } else { - if (unlikely(ss_size < min_ss_size)) - ret = -ENOMEM; - if (!sigaltstack_size_valid(ss_size)) - ret = -ENOMEM; - } - if (!ret) { - t->sas_ss_sp = (unsigned long) ss_sp; - t->sas_ss_size = ss_size; - t->sas_ss_flags = ss_flags; + + if (unlikely(ss_size < min_ss_size) || + unlikely(!sigaltstack_size_valid(ss_size))) { + sigaltstack_unlock(); + return -ENOMEM; } + + t->sas_ss_sp = (unsigned long) ss_sp; + t->sas_ss_size = ss_size; + t->sas_ss_flags = ss_flags; + sigaltstack_unlock(); } - return ret; + return 0; } SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) _