brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · 07227fa Raw
198 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Stas Sergeev <stsp@users.sourceforge.net>4 *5 * test sigaltstack(SS_ONSTACK | SS_AUTODISARM)6 * If that succeeds, then swapcontext() can be used inside sighandler safely.7 *8 */9 10#define _GNU_SOURCE11#include <signal.h>12#include <stdio.h>13#include <stdlib.h>14#include <sys/mman.h>15#include <ucontext.h>16#include <alloca.h>17#include <string.h>18#include <assert.h>19#include <errno.h>20#include <sys/auxv.h>21 22#include "../kselftest.h"23#include "current_stack_pointer.h"24 25#ifndef SS_AUTODISARM26#define SS_AUTODISARM  (1U << 31)27#endif28 29#ifndef AT_MINSIGSTKSZ30#define AT_MINSIGSTKSZ	5131#endif32 33static unsigned int stack_size;34static void *sstack, *ustack;35static ucontext_t uc, sc;36static const char *msg = "[OK]\tStack preserved";37static const char *msg2 = "[FAIL]\tStack corrupted";38struct stk_data {39	char msg[128];40	int flag;41};42 43void my_usr1(int sig, siginfo_t *si, void *u)44{45	char *aa;46	int err;47	stack_t stk;48	struct stk_data *p;49 50	if (sp < (unsigned long)sstack ||51			sp >= (unsigned long)sstack + stack_size) {52		ksft_exit_fail_msg("SP is not on sigaltstack\n");53	}54	/* put some data on stack. other sighandler will try to overwrite it */55	aa = alloca(1024);56	assert(aa);57	p = (struct stk_data *)(aa + 512);58	strcpy(p->msg, msg);59	p->flag = 1;60	ksft_print_msg("[RUN]\tsignal USR1\n");61	err = sigaltstack(NULL, &stk);62	if (err) {63		ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));64		exit(EXIT_FAILURE);65	}66	if (stk.ss_flags != SS_DISABLE)67		ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",68				stk.ss_flags);69	else70		ksft_test_result_pass(71				"sigaltstack is disabled in sighandler\n");72	swapcontext(&sc, &uc);73	ksft_print_msg("%s\n", p->msg);74	if (!p->flag) {75		ksft_exit_fail_msg("[RUN]\tAborting\n");76		exit(EXIT_FAILURE);77	}78}79 80void my_usr2(int sig, siginfo_t *si, void *u)81{82	char *aa;83	struct stk_data *p;84 85	ksft_print_msg("[RUN]\tsignal USR2\n");86	aa = alloca(1024);87	/* dont run valgrind on this */88	/* try to find the data stored by previous sighandler */89	p = memmem(aa, 1024, msg, strlen(msg));90	if (p) {91		ksft_test_result_fail("sigaltstack re-used\n");92		/* corrupt the data */93		strcpy(p->msg, msg2);94		/* tell other sighandler that his data is corrupted */95		p->flag = 0;96	}97}98 99static void switch_fn(void)100{101	ksft_print_msg("[RUN]\tswitched to user ctx\n");102	raise(SIGUSR2);103	setcontext(&sc);104}105 106int main(void)107{108	struct sigaction act;109	stack_t stk;110	int err;111 112	/* Make sure more than the required minimum. */113	stack_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;114	ksft_print_msg("[NOTE]\tthe stack size is %u\n", stack_size);115 116	ksft_print_header();117	ksft_set_plan(3);118 119	sigemptyset(&act.sa_mask);120	act.sa_flags = SA_ONSTACK | SA_SIGINFO;121	act.sa_sigaction = my_usr1;122	sigaction(SIGUSR1, &act, NULL);123	act.sa_sigaction = my_usr2;124	sigaction(SIGUSR2, &act, NULL);125	sstack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,126		      MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);127	if (sstack == MAP_FAILED) {128		ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));129		return EXIT_FAILURE;130	}131 132	err = sigaltstack(NULL, &stk);133	if (err) {134		ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));135		exit(EXIT_FAILURE);136	}137	if (stk.ss_flags == SS_DISABLE) {138		ksft_test_result_pass(139				"Initial sigaltstack state was SS_DISABLE\n");140	} else {141		ksft_exit_fail_msg("Initial sigaltstack state was %x; "142		       "should have been SS_DISABLE\n", stk.ss_flags);143		return EXIT_FAILURE;144	}145 146	stk.ss_sp = sstack;147	stk.ss_size = stack_size;148	stk.ss_flags = SS_ONSTACK | SS_AUTODISARM;149	err = sigaltstack(&stk, NULL);150	if (err) {151		if (errno == EINVAL) {152			ksft_test_result_skip(153				"[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");154			/*155			 * If test cases for the !SS_AUTODISARM variant were156			 * added, we could still run them.  We don't have any157			 * test cases like that yet, so just exit and report158			 * success.159			 */160			return 0;161		} else {162			ksft_exit_fail_msg(163				"sigaltstack(SS_ONSTACK | SS_AUTODISARM)  %s\n",164					strerror(errno));165			return EXIT_FAILURE;166		}167	}168 169	ustack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,170		      MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);171	if (ustack == MAP_FAILED) {172		ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));173		return EXIT_FAILURE;174	}175	getcontext(&uc);176	uc.uc_link = NULL;177	uc.uc_stack.ss_sp = ustack;178	uc.uc_stack.ss_size = stack_size;179	makecontext(&uc, switch_fn, 0);180	raise(SIGUSR1);181 182	err = sigaltstack(NULL, &stk);183	if (err) {184		ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));185		exit(EXIT_FAILURE);186	}187	if (stk.ss_flags != SS_AUTODISARM) {188		ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",189				stk.ss_flags);190		exit(EXIT_FAILURE);191	}192	ksft_test_result_pass(193			"sigaltstack is still SS_AUTODISARM after signal\n");194 195	ksft_exit_pass();196	return 0;197}198