Home | History | Annotate | Line # | Download | only in gen
t_siginfo.c revision 1.39
      1 /* $NetBSD: t_siginfo.c,v 1.39 2020/02/22 19:09:51 kamil Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <atf-c.h>
     30 
     31 #include <sys/resource.h>
     32 #include <sys/sysctl.h>
     33 #include <sys/time.h>
     34 #include <sys/ucontext.h>
     35 #include <sys/wait.h>
     36 
     37 #include <assert.h>
     38 #include <float.h>
     39 #include <inttypes.h>
     40 #include <setjmp.h>
     41 #include <signal.h>
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 #include <unistd.h>
     46 
     47 #include <fenv.h>
     48 #ifdef __HAVE_FENV
     49 #include <ieeefp.h>	/* only need for ARM Cortex/Neon hack */
     50 #elif defined(_FLOAT_IEEE754)
     51 #include <ieeefp.h>
     52 #endif
     53 
     54 #include "isqemu.h"
     55 
     56 #ifdef ENABLE_TESTS
     57 /* for sigbus */
     58 volatile char *addr;
     59 
     60 /* for sigchild */
     61 pid_t child;
     62 int code;
     63 int status;
     64 
     65 /* for sigfpe */
     66 sig_atomic_t fltdiv_signalled = 0;
     67 sig_atomic_t intdiv_signalled = 0;
     68 
     69 static void
     70 sig_debug(int signo, siginfo_t *info, ucontext_t *ctx)
     71 {
     72 	unsigned int i;
     73 
     74 	printf("%d %p %p\n", signo, info, ctx);
     75 	if (info != NULL) {
     76 		printf("si_signo=%d\n", info->si_signo);
     77 		printf("si_errno=%d\n", info->si_errno);
     78 		printf("si_code=%d\n", info->si_code);
     79 		printf("si_value.sival_int=%d\n", info->si_value.sival_int);
     80 	}
     81 	if (ctx != NULL) {
     82 		printf("uc_flags 0x%x\n", ctx->uc_flags);
     83 		printf("uc_link %p\n", ctx->uc_link);
     84 		for (i = 0; i < __arraycount(ctx->uc_sigmask.__bits); i++)
     85 			printf("uc_sigmask[%d] 0x%x\n", i,
     86 			    ctx->uc_sigmask.__bits[i]);
     87 		printf("uc_stack %p %lu 0x%x\n", ctx->uc_stack.ss_sp,
     88 		    (unsigned long)ctx->uc_stack.ss_size,
     89 		    ctx->uc_stack.ss_flags);
     90 		for (i = 0; i < __arraycount(ctx->uc_mcontext.__gregs); i++)
     91 			printf("uc_mcontext.greg[%d] 0x%lx\n", i,
     92 			    (long)ctx->uc_mcontext.__gregs[i]);
     93 	}
     94 }
     95 
     96 static void
     97 sigalrm_action(int signo, siginfo_t *info, void *ptr)
     98 {
     99 
    100 	sig_debug(signo, info, (ucontext_t *)ptr);
    101 
    102 	ATF_REQUIRE_EQ(info->si_signo, SIGALRM);
    103 	ATF_REQUIRE_EQ(info->si_code, SI_TIMER);
    104 	ATF_REQUIRE_EQ(info->si_value.sival_int, ITIMER_REAL);
    105 
    106 	atf_tc_pass();
    107 	/* NOTREACHED */
    108 }
    109 
    110 ATF_TC(sigalarm);
    111 
    112 ATF_TC_HEAD(sigalarm, tc)
    113 {
    114 
    115 	atf_tc_set_md_var(tc, "descr",
    116 	    "Checks that signal trampoline correctly calls SIGALRM handler");
    117 }
    118 
    119 ATF_TC_BODY(sigalarm, tc)
    120 {
    121 	struct sigaction sa;
    122 	sa.sa_flags = SA_SIGINFO;
    123 	sa.sa_sigaction = sigalrm_action;
    124 	sigemptyset(&sa.sa_mask);
    125 	sigaction(SIGALRM, &sa, NULL);
    126 	for (;;) {
    127 		alarm(1);
    128 		sleep(1);
    129 	}
    130 	atf_tc_fail("SIGALRM handler wasn't called");
    131 }
    132 
    133 static void
    134 sigchild_action(int signo, siginfo_t *info, void *ptr)
    135 {
    136 	if (info != NULL) {
    137 		printf("info=%p\n", info);
    138 		printf("ptr=%p\n", ptr);
    139 		printf("si_signo=%d\n", info->si_signo);
    140 		printf("si_errno=%d\n", info->si_errno);
    141 		printf("si_code=%d\n", info->si_code);
    142 		printf("si_uid=%d\n", info->si_uid);
    143 		printf("si_pid=%d\n", info->si_pid);
    144 		printf("si_status=%d\n", info->si_status);
    145 		printf("si_utime=%lu\n", (unsigned long int)info->si_utime);
    146 		printf("si_stime=%lu\n", (unsigned long int)info->si_stime);
    147 	}
    148 	ATF_REQUIRE_EQ(info->si_code, code);
    149 	ATF_REQUIRE_EQ(info->si_signo, SIGCHLD);
    150 	ATF_REQUIRE_EQ(info->si_uid, getuid());
    151 	ATF_REQUIRE_EQ(info->si_pid, child);
    152 	if (WIFEXITED(info->si_status))
    153 		ATF_REQUIRE_EQ(WEXITSTATUS(info->si_status), status);
    154 	else if (WIFSTOPPED(info->si_status))
    155 		ATF_REQUIRE_EQ(WSTOPSIG(info->si_status), status);
    156 	else if (WIFSIGNALED(info->si_status))
    157 		ATF_REQUIRE_EQ(WTERMSIG(info->si_status), status);
    158 }
    159 
    160 static void
    161 setchildhandler(void (*action)(int, siginfo_t *, void *))
    162 {
    163 	struct sigaction sa;
    164 	sa.sa_flags = SA_SIGINFO;
    165 	sa.sa_sigaction = action;
    166 	sigemptyset(&sa.sa_mask);
    167 	sigaction(SIGCHLD, &sa, NULL);
    168 }
    169 
    170 static void
    171 sigchild_setup(void)
    172 {
    173 	sigset_t set;
    174 	struct rlimit rlim;
    175 
    176 	(void)getrlimit(RLIMIT_CORE, &rlim);
    177 	rlim.rlim_cur = rlim.rlim_max;
    178 	(void)setrlimit(RLIMIT_CORE, &rlim);
    179 
    180 	setchildhandler(sigchild_action);
    181 	sigemptyset(&set);
    182 	sigaddset(&set, SIGCHLD);
    183 	sigprocmask(SIG_BLOCK, &set, NULL);
    184 }
    185 
    186 ATF_TC(sigchild_normal);
    187 ATF_TC_HEAD(sigchild_normal, tc)
    188 {
    189 
    190 	atf_tc_set_md_var(tc, "descr",
    191 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    192 	    "when child exits normally");
    193 }
    194 
    195 ATF_TC_BODY(sigchild_normal, tc)
    196 {
    197 	sigset_t set;
    198 
    199 	sigchild_setup();
    200 
    201 	status = 25;
    202 	code = CLD_EXITED;
    203 
    204 	switch ((child = fork())) {
    205 	case 0:
    206 		sleep(1);
    207 		exit(status);
    208 	case -1:
    209 		atf_tc_fail("fork failed");
    210 	default:
    211 		sigemptyset(&set);
    212 		sigsuspend(&set);
    213 	}
    214 }
    215 
    216 ATF_TC(sigchild_dump);
    217 ATF_TC_HEAD(sigchild_dump, tc)
    218 {
    219 
    220 	atf_tc_set_md_var(tc, "descr",
    221 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    222 	    "when child segfaults");
    223 }
    224 
    225 ATF_TC_BODY(sigchild_dump, tc)
    226 {
    227 	sigset_t set;
    228 
    229 	sigchild_setup();
    230 
    231 	status = SIGSEGV;
    232 	code = CLD_DUMPED;
    233 
    234 	switch ((child = fork())) {
    235 	case 0:
    236 		sleep(1);
    237 		*(volatile long *)0 = 0;
    238 		atf_tc_fail("Child did not segfault");
    239 		/* NOTREACHED */
    240 	case -1:
    241 		atf_tc_fail("fork failed");
    242 	default:
    243 		sigemptyset(&set);
    244 		sigsuspend(&set);
    245 	}
    246 }
    247 
    248 ATF_TC(sigchild_kill);
    249 ATF_TC_HEAD(sigchild_kill, tc)
    250 {
    251 
    252 	atf_tc_set_md_var(tc, "descr",
    253 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    254 	    "when child is killed");
    255 }
    256 
    257 ATF_TC_BODY(sigchild_kill, tc)
    258 {
    259 	sigset_t set;
    260 
    261 	sigchild_setup();
    262 
    263 	status = SIGPIPE;
    264 	code = CLD_KILLED;
    265 
    266 	switch ((child = fork())) {
    267 	case 0:
    268 		sigemptyset(&set);
    269 		sigsuspend(&set);
    270 		break;
    271 	case -1:
    272 		atf_tc_fail("fork failed");
    273 	default:
    274 		kill(child, SIGPIPE);
    275 		sigemptyset(&set);
    276 		sigsuspend(&set);
    277 	}
    278 }
    279 
    280 static sigjmp_buf sigfpe_flt_env;
    281 static void
    282 sigfpe_flt_action(int signo, siginfo_t *info, void *ptr)
    283 {
    284 
    285 	sig_debug(signo, info, (ucontext_t *)ptr);
    286 
    287 	if (fltdiv_signalled++ != 0)
    288 		atf_tc_fail("FPE handler called more than once");
    289 
    290 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
    291 	ATF_REQUIRE_EQ(info->si_code, FPE_FLTDIV);
    292 	ATF_REQUIRE_EQ(info->si_errno, 0);
    293 
    294 	siglongjmp(sigfpe_flt_env, 1);
    295 }
    296 
    297 ATF_TC(sigfpe_flt);
    298 ATF_TC_HEAD(sigfpe_flt, tc)
    299 {
    300 
    301 	atf_tc_set_md_var(tc, "descr",
    302 	    "Checks that signal trampoline correctly calls SIGFPE handler "
    303 	    "for floating div-by-zero");
    304 }
    305 
    306 ATF_TC_BODY(sigfpe_flt, tc)
    307 {
    308 	struct sigaction sa;
    309 	double d = strtod("0", NULL);
    310 
    311 	if (isQEMU())
    312 		atf_tc_skip("Test does not run correctly under QEMU");
    313 #if (__arm__ && !__SOFTFP__) || __aarch64__
    314 	/*
    315 	 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
    316 	 * skip these tests if running on them and compiled for
    317 	 * hard float.
    318 	 */
    319 	if (0 == fpsetmask(fpsetmask(FP_X_INV)))
    320 		atf_tc_skip("FPU does not implement traps on FP exceptions");
    321 #endif
    322 	if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
    323 		sa.sa_flags = SA_SIGINFO;
    324 		sa.sa_sigaction = sigfpe_flt_action;
    325 		sigemptyset(&sa.sa_mask);
    326 		sigaction(SIGFPE, &sa, NULL);
    327 #ifdef __HAVE_FENV
    328 		feenableexcept(FE_ALL_EXCEPT);
    329 #elif defined(_FLOAT_IEEE754)
    330 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
    331 #endif
    332 		printf("%g\n", 1 / d);
    333 	}
    334 	if (fltdiv_signalled == 0)
    335 		atf_tc_fail("FPE signal handler was not invoked");
    336 }
    337 
    338 static sigjmp_buf sigfpe_int_env;
    339 static void
    340 sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
    341 {
    342 
    343 	sig_debug(signo, info, (ucontext_t *)ptr);
    344 
    345 	if (intdiv_signalled++ != 0)
    346 		atf_tc_fail("INTDIV handler called more than once");
    347 
    348 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
    349 	ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
    350 	atf_tc_expect_pass();
    351 	ATF_REQUIRE_EQ(info->si_errno, 0);
    352 
    353 	siglongjmp(sigfpe_int_env, 1);
    354 }
    355 
    356 ATF_TC(sigfpe_int);
    357 ATF_TC_HEAD(sigfpe_int, tc)
    358 {
    359 
    360 	atf_tc_set_md_var(tc, "descr",
    361 	    "Checks that signal trampoline correctly calls SIGFPE handler "
    362 	    "for integer div-by-zero (PR port-i386/43655)");
    363 }
    364 
    365 ATF_TC_BODY(sigfpe_int, tc)
    366 {
    367 	struct sigaction sa;
    368 	long l = strtol("0", NULL, 10);
    369 
    370 #if defined(__powerpc__) || defined(__aarch64__)
    371 	atf_tc_skip("Integer division by zero doesn't trap");
    372 #endif
    373 	if (sigsetjmp(sigfpe_int_env, 0) == 0) {
    374 		sa.sa_flags = SA_SIGINFO;
    375 		sa.sa_sigaction = sigfpe_int_action;
    376 		sigemptyset(&sa.sa_mask);
    377 		sigaction(SIGFPE, &sa, NULL);
    378 #ifdef __HAVE_FENV
    379 		feenableexcept(FE_ALL_EXCEPT);
    380 #elif defined(_FLOAT_IEEE754)
    381 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
    382 #endif
    383 		printf("%ld\n", 1 / l);
    384 	}
    385 	if (intdiv_signalled == 0)
    386 		atf_tc_fail("FPE signal handler was not invoked");
    387 }
    388 
    389 static void
    390 sigsegv_action(int signo, siginfo_t *info, void *ptr)
    391 {
    392 
    393 	sig_debug(signo, info, (ucontext_t *)ptr);
    394 
    395 	ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
    396 	ATF_REQUIRE_EQ(info->si_errno, 0);
    397 	ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
    398 	ATF_REQUIRE_EQ(info->si_addr, (void *)0);
    399 
    400 	atf_tc_pass();
    401 	/* NOTREACHED */
    402 }
    403 
    404 ATF_TC(sigsegv);
    405 ATF_TC_HEAD(sigsegv, tc)
    406 {
    407 
    408 	atf_tc_set_md_var(tc, "descr",
    409 	    "Checks that signal trampoline correctly calls SIGSEGV handler");
    410 }
    411 
    412 ATF_TC_BODY(sigsegv, tc)
    413 {
    414 	struct sigaction sa;
    415 
    416 	sa.sa_flags = SA_SIGINFO;
    417 	sa.sa_sigaction = sigsegv_action;
    418 	sigemptyset(&sa.sa_mask);
    419 	sigaction(SIGSEGV, &sa, NULL);
    420 
    421 	*(volatile long *)0 = 0;
    422 	atf_tc_fail("Test did not fault as expected");
    423 }
    424 
    425 static void
    426 sigbus_action(int signo, siginfo_t *info, void *ptr)
    427 {
    428 
    429 	printf("si_addr = %p\n", info->si_addr);
    430 	sig_debug(signo, info, (ucontext_t *)ptr);
    431 
    432 	ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
    433 	ATF_REQUIRE_EQ(info->si_errno, 0);
    434 	ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
    435 
    436 #if defined(__i386__) || defined(__x86_64__)
    437 	atf_tc_expect_fail("x86 architecture does not correctly "
    438 	    "report the address where the unaligned access occured");
    439 #endif
    440 	ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
    441 
    442 	atf_tc_pass();
    443 	/* NOTREACHED */
    444 }
    445 
    446 ATF_TC(sigbus_adraln);
    447 ATF_TC_HEAD(sigbus_adraln, tc)
    448 {
    449 
    450 	atf_tc_set_md_var(tc, "descr",
    451 	    "Checks that signal trampoline correctly calls SIGBUS handler "
    452 	    "for invalid address alignment");
    453 }
    454 
    455 ATF_TC_BODY(sigbus_adraln, tc)
    456 {
    457 	struct sigaction sa;
    458 
    459 #if defined(__alpha__) || defined(__arm__)
    460 	int rv, val;
    461 	size_t len = sizeof(val);
    462 	rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
    463 	ATF_REQUIRE(rv == 0);
    464 	if (val == 0)
    465 		atf_tc_skip("No SIGBUS signal for unaligned accesses");
    466 #endif
    467 
    468 	/* m68k (except sun2) never issue SIGBUS (PR lib/49653),
    469 	 * same for armv8 or newer */
    470 	if (strcmp(MACHINE_ARCH, "m68k") == 0 ||
    471 	    strcmp(MACHINE_ARCH, "aarch64") == 0)
    472 		atf_tc_skip("No SIGBUS signal for unaligned accesses");
    473 
    474 	sa.sa_flags = SA_SIGINFO;
    475 	sa.sa_sigaction = sigbus_action;
    476 	sigemptyset(&sa.sa_mask);
    477 	sigaction(SIGBUS, &sa, NULL);
    478 
    479 	/* Enable alignment checks for x86. 0x40000 is PSL_AC. */
    480 #if defined(__i386__)
    481 	__asm__("pushf; orl $0x40000, (%esp); popf");
    482 #elif defined(__amd64__)
    483 	__asm__("pushf; orl $0x40000, (%rsp); popf");
    484 #endif
    485 
    486 	addr = calloc(2, sizeof(int));
    487 	ATF_REQUIRE(addr != NULL);
    488 
    489 	if (isQEMU())
    490 		atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
    491 
    492 	/* Force an unaligned access */
    493 	addr++;
    494 	printf("now trying to access unaligned address %p\n", addr);
    495 	ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
    496 
    497 	atf_tc_fail("Test did not fault as expected");
    498 }
    499 
    500 #else
    501 ATF_TC(dummy);
    502 ATF_TC_HEAD(dummy, tc)
    503 {
    504 	atf_tc_set_md_var(tc, "descr", "A dummy test");
    505 }
    506 
    507 ATF_TC_BODY(dummy, tc)
    508 {
    509 
    510 	// Dummy, skipped
    511 	// The ATF framework requires at least a single defined test.
    512 }
    513 #endif
    514 
    515 ATF_TP_ADD_TCS(tp)
    516 {
    517 
    518 #ifdef ENABLE_TESTS
    519 	ATF_TP_ADD_TC(tp, sigalarm);
    520 	ATF_TP_ADD_TC(tp, sigchild_normal);
    521 	ATF_TP_ADD_TC(tp, sigchild_dump);
    522 	ATF_TP_ADD_TC(tp, sigchild_kill);
    523 	ATF_TP_ADD_TC(tp, sigfpe_flt);
    524 	ATF_TP_ADD_TC(tp, sigfpe_int);
    525 	ATF_TP_ADD_TC(tp, sigsegv);
    526 	ATF_TP_ADD_TC(tp, sigbus_adraln);
    527 #else
    528 	ATF_TP_ADD_TC(tp, dummy);
    529 #endif
    530 
    531 	return atf_no_error();
    532 }
    533