Currently sigaltstack() can return multiple flags, for example SS_DISABLE|SS_AUTODISARM. This confuses libraries (including asan runtime) and contradicts the man page.
Patch 1 fixes this problem by ignoring any flag passed with SS_DISABLE. Patch 2 adds a test-case for that scenario.
Signed-off-by: Stas Sergeev stsp2@yandex.ru CC: "Eric W. Biederman" ebiederm@xmission.com CC: Kees Cook keescook@chromium.org CC: Jens Axboe axboe@kernel.dk CC: Peter Zijlstra peterz@infradead.org CC: Marco Elver elver@google.com CC: Thomas Gleixner tglx@linutronix.de CC: Alexey Gladkov legion@kernel.org CC: Andrew Lutomirski luto@mit.edu CC: Shuah Khan shuah@kernel.org CC: "Chang S. Bae" chang.seok.bae@intel.com CC: Borislav Petkov bp@suse.de CC: Thomas Gleixner tglx@linutronix.de CC: Len Brown len.brown@intel.com CC: linux-kselftest@vger.kernel.org CC: linux-kernel@vger.kernel.org
Stas Sergeev (2): sigaltstack: ignore flags if SS_DISABLE is set selftests: sigaltstack: add new SS_DISABLE test
kernel/signal.c | 1 + tools/testing/selftests/sigaltstack/sas.c | 48 ++++++++++++----------- 2 files changed, 26 insertions(+), 23 deletions(-)
This test makes sure that when SS_DISABLE is used, all other flags are ignored.
Also remove unneeded exit()s after ksft_exit_fail_msg(). That function exits by itself.
Signed-off-by: Stas Sergeev stsp2@yandex.ru CC: Shuah Khan shuah@kernel.org CC: "Chang S. Bae" chang.seok.bae@intel.com CC: Borislav Petkov bp@suse.de CC: Thomas Gleixner tglx@linutronix.de CC: Len Brown len.brown@intel.com CC: linux-kselftest@vger.kernel.org CC: linux-kernel@vger.kernel.org --- tools/testing/selftests/sigaltstack/sas.c | 48 ++++++++++++----------- 1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c index c53b070755b6..7be377e84aa0 100644 --- a/tools/testing/selftests/sigaltstack/sas.c +++ b/tools/testing/selftests/sigaltstack/sas.c @@ -119,7 +119,7 @@ int main(void) ksft_print_msg("[NOTE]\tthe stack size is %lu\n", stack_size);
ksft_print_header(); - ksft_set_plan(3); + ksft_set_plan(4);
sigemptyset(&act.sa_mask); act.sa_flags = SA_ONSTACK | SA_SIGINFO; @@ -129,24 +129,18 @@ int main(void) sigaction(SIGUSR2, &act, NULL); sstack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); - if (sstack == MAP_FAILED) { + if (sstack == MAP_FAILED) ksft_exit_fail_msg("mmap() - %s\n", strerror(errno)); - return EXIT_FAILURE; - }
err = sigaltstack(NULL, &stk); - if (err) { + if (err) ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - if (stk.ss_flags == SS_DISABLE) { + if (stk.ss_flags == SS_DISABLE) ksft_test_result_pass( "Initial sigaltstack state was SS_DISABLE\n"); - } else { + else ksft_exit_fail_msg("Initial sigaltstack state was %x; " "should have been SS_DISABLE\n", stk.ss_flags); - return EXIT_FAILURE; - }
stk.ss_sp = sstack; stk.ss_size = stack_size; @@ -167,16 +161,13 @@ int main(void) ksft_exit_fail_msg( "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n", strerror(errno)); - return EXIT_FAILURE; } }
ustack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); - if (ustack == MAP_FAILED) { + if (ustack == MAP_FAILED) ksft_exit_fail_msg("mmap() - %s\n", strerror(errno)); - return EXIT_FAILURE; - } getcontext(&uc); uc.uc_link = NULL; uc.uc_stack.ss_sp = ustack; @@ -185,17 +176,28 @@ int main(void) raise(SIGUSR1);
err = sigaltstack(NULL, &stk); - if (err) { + if (err) ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - if (stk.ss_flags != SS_AUTODISARM) { - ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n", + if (stk.ss_flags != SS_AUTODISARM) + ksft_test_result_fail("ss_flags=%x, should be SS_AUTODISARM\n", stk.ss_flags); - exit(EXIT_FAILURE); - } - ksft_test_result_pass( + else + ksft_test_result_pass( "sigaltstack is still SS_AUTODISARM after signal\n"); + /* We are done, disable SS and exit. */ + stk.ss_flags = SS_DISABLE | SS_AUTODISARM; + err = sigaltstack(&stk, NULL); + if (err) + ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno)); + err = sigaltstack(NULL, &stk); + if (err) + ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno)); + if (stk.ss_flags != SS_DISABLE) + ksft_test_result_fail("ss_flags=%x, should be SS_DISABLE\n", + stk.ss_flags); + else + ksft_test_result_pass( + "sigaltstack disabled\n");
ksft_exit_pass(); return 0;
linux-kselftest-mirror@lists.linaro.org