0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define _GNU_SOURCE
0011 #include <signal.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <sys/mman.h>
0015 #include <ucontext.h>
0016 #include <alloca.h>
0017 #include <string.h>
0018 #include <assert.h>
0019 #include <errno.h>
0020 #include <sys/auxv.h>
0021
0022 #include "../kselftest.h"
0023
0024 #ifndef SS_AUTODISARM
0025 #define SS_AUTODISARM (1U << 31)
0026 #endif
0027
0028 #ifndef AT_MINSIGSTKSZ
0029 #define AT_MINSIGSTKSZ 51
0030 #endif
0031
0032 static unsigned int stack_size;
0033 static void *sstack, *ustack;
0034 static ucontext_t uc, sc;
0035 static const char *msg = "[OK]\tStack preserved";
0036 static const char *msg2 = "[FAIL]\tStack corrupted";
0037 struct stk_data {
0038 char msg[128];
0039 int flag;
0040 };
0041
0042 void my_usr1(int sig, siginfo_t *si, void *u)
0043 {
0044 char *aa;
0045 int err;
0046 stack_t stk;
0047 struct stk_data *p;
0048
0049 #if __s390x__
0050 register unsigned long sp asm("%15");
0051 #else
0052 register unsigned long sp asm("sp");
0053 #endif
0054
0055 if (sp < (unsigned long)sstack ||
0056 sp >= (unsigned long)sstack + stack_size) {
0057 ksft_exit_fail_msg("SP is not on sigaltstack\n");
0058 }
0059
0060 aa = alloca(1024);
0061 assert(aa);
0062 p = (struct stk_data *)(aa + 512);
0063 strcpy(p->msg, msg);
0064 p->flag = 1;
0065 ksft_print_msg("[RUN]\tsignal USR1\n");
0066 err = sigaltstack(NULL, &stk);
0067 if (err) {
0068 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
0069 exit(EXIT_FAILURE);
0070 }
0071 if (stk.ss_flags != SS_DISABLE)
0072 ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
0073 stk.ss_flags);
0074 else
0075 ksft_test_result_pass(
0076 "sigaltstack is disabled in sighandler\n");
0077 swapcontext(&sc, &uc);
0078 ksft_print_msg("%s\n", p->msg);
0079 if (!p->flag) {
0080 ksft_exit_fail_msg("[RUN]\tAborting\n");
0081 exit(EXIT_FAILURE);
0082 }
0083 }
0084
0085 void my_usr2(int sig, siginfo_t *si, void *u)
0086 {
0087 char *aa;
0088 struct stk_data *p;
0089
0090 ksft_print_msg("[RUN]\tsignal USR2\n");
0091 aa = alloca(1024);
0092
0093
0094 p = memmem(aa, 1024, msg, strlen(msg));
0095 if (p) {
0096 ksft_test_result_fail("sigaltstack re-used\n");
0097
0098 strcpy(p->msg, msg2);
0099
0100 p->flag = 0;
0101 }
0102 }
0103
0104 static void switch_fn(void)
0105 {
0106 ksft_print_msg("[RUN]\tswitched to user ctx\n");
0107 raise(SIGUSR2);
0108 setcontext(&sc);
0109 }
0110
0111 int main(void)
0112 {
0113 struct sigaction act;
0114 stack_t stk;
0115 int err;
0116
0117
0118 stack_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;
0119 ksft_print_msg("[NOTE]\tthe stack size is %lu\n", stack_size);
0120
0121 ksft_print_header();
0122 ksft_set_plan(3);
0123
0124 sigemptyset(&act.sa_mask);
0125 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
0126 act.sa_sigaction = my_usr1;
0127 sigaction(SIGUSR1, &act, NULL);
0128 act.sa_sigaction = my_usr2;
0129 sigaction(SIGUSR2, &act, NULL);
0130 sstack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
0131 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
0132 if (sstack == MAP_FAILED) {
0133 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
0134 return EXIT_FAILURE;
0135 }
0136
0137 err = sigaltstack(NULL, &stk);
0138 if (err) {
0139 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
0140 exit(EXIT_FAILURE);
0141 }
0142 if (stk.ss_flags == SS_DISABLE) {
0143 ksft_test_result_pass(
0144 "Initial sigaltstack state was SS_DISABLE\n");
0145 } else {
0146 ksft_exit_fail_msg("Initial sigaltstack state was %x; "
0147 "should have been SS_DISABLE\n", stk.ss_flags);
0148 return EXIT_FAILURE;
0149 }
0150
0151 stk.ss_sp = sstack;
0152 stk.ss_size = stack_size;
0153 stk.ss_flags = SS_ONSTACK | SS_AUTODISARM;
0154 err = sigaltstack(&stk, NULL);
0155 if (err) {
0156 if (errno == EINVAL) {
0157 ksft_test_result_skip(
0158 "[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
0159
0160
0161
0162
0163
0164
0165 return 0;
0166 } else {
0167 ksft_exit_fail_msg(
0168 "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
0169 strerror(errno));
0170 return EXIT_FAILURE;
0171 }
0172 }
0173
0174 ustack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
0175 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
0176 if (ustack == MAP_FAILED) {
0177 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
0178 return EXIT_FAILURE;
0179 }
0180 getcontext(&uc);
0181 uc.uc_link = NULL;
0182 uc.uc_stack.ss_sp = ustack;
0183 uc.uc_stack.ss_size = stack_size;
0184 makecontext(&uc, switch_fn, 0);
0185 raise(SIGUSR1);
0186
0187 err = sigaltstack(NULL, &stk);
0188 if (err) {
0189 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
0190 exit(EXIT_FAILURE);
0191 }
0192 if (stk.ss_flags != SS_AUTODISARM) {
0193 ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
0194 stk.ss_flags);
0195 exit(EXIT_FAILURE);
0196 }
0197 ksft_test_result_pass(
0198 "sigaltstack is still SS_AUTODISARM after signal\n");
0199
0200 ksft_exit_pass();
0201 return 0;
0202 }