Home | History | Annotate | Line # | Download | only in gen
t_siginfo.c revision 1.24
      1 /* $NetBSD: t_siginfo.c,v 1.24 2014/11/04 00:20:19 justin 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/inttypes.h>
     32 #include <sys/resource.h>
     33 #include <sys/sysctl.h>
     34 #include <sys/time.h>
     35 #include <sys/ucontext.h>
     36 #include <sys/wait.h>
     37 
     38 #include <assert.h>
     39 #include <signal.h>
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <unistd.h>
     44 #include <setjmp.h>
     45 #include <float.h>
     46 
     47 #ifdef HAVE_FENV
     48 #include <fenv.h>
     49 #elif defined(_FLOAT_IEEE754)
     50 #include <ieeefp.h>
     51 #endif
     52 
     53 #include "isqemu.h"
     54 
     55 /* for sigbus */
     56 volatile char *addr;
     57 
     58 /* for sigchild */
     59 pid_t child;
     60 int code;
     61 int status;
     62 
     63 /* for sigfpe */
     64 sig_atomic_t fltdiv_signalled = 0;
     65 sig_atomic_t intdiv_signalled = 0;
     66 
     67 static void
     68 sig_debug(int signo, siginfo_t *info, ucontext_t *ctx)
     69 {
     70 	unsigned int i;
     71 
     72 	printf("%d %p %p\n", signo, info, ctx);
     73 	if (info != NULL) {
     74 		printf("si_signo=%d\n", info->si_signo);
     75 		printf("si_errno=%d\n", info->si_errno);
     76 		printf("si_code=%d\n", info->si_code);
     77 		printf("si_value.sival_int=%d\n", info->si_value.sival_int);
     78 	}
     79 	if (ctx != NULL) {
     80 		printf("uc_flags 0x%x\n", ctx->uc_flags);
     81 		printf("uc_link %p\n", ctx->uc_link);
     82 		for (i = 0; i < __arraycount(ctx->uc_sigmask.__bits); i++)
     83 			printf("uc_sigmask[%d] 0x%x\n", i,
     84 			    ctx->uc_sigmask.__bits[i]);
     85 		printf("uc_stack %p %lu 0x%x\n", ctx->uc_stack.ss_sp,
     86 		    (unsigned long)ctx->uc_stack.ss_size,
     87 		    ctx->uc_stack.ss_flags);
     88 		for (i = 0; i < __arraycount(ctx->uc_mcontext.__gregs); i++)
     89 			printf("uc_mcontext.greg[%d] 0x%lx\n", i,
     90 			    (long)ctx->uc_mcontext.__gregs[i]);
     91 	}
     92 }
     93 
     94 static void
     95 sigalrm_action(int signo, siginfo_t *info, void *ptr)
     96 {
     97 
     98 	sig_debug(signo, info, (ucontext_t *)ptr);
     99 
    100 	ATF_REQUIRE_EQ(info->si_signo, SIGALRM);
    101 	ATF_REQUIRE_EQ(info->si_code, SI_TIMER);
    102 	ATF_REQUIRE_EQ(info->si_value.sival_int, ITIMER_REAL);
    103 
    104 	atf_tc_pass();
    105 	/* NOTREACHED */
    106 }
    107 
    108 ATF_TC(sigalarm);
    109 
    110 ATF_TC_HEAD(sigalarm, tc)
    111 {
    112 
    113 	atf_tc_set_md_var(tc, "descr",
    114 	    "Checks that signal trampoline correctly calls SIGALRM handler");
    115 }
    116 
    117 ATF_TC_BODY(sigalarm, tc)
    118 {
    119 	struct sigaction sa;
    120 	sa.sa_flags = SA_SIGINFO;
    121 	sa.sa_sigaction = sigalrm_action;
    122 	sigemptyset(&sa.sa_mask);
    123 	sigaction(SIGALRM, &sa, NULL);
    124 	for (;;) {
    125 		alarm(1);
    126 		sleep(1);
    127 	}
    128 	atf_tc_fail("SIGALRM handler wasn't called");
    129 }
    130 
    131 static void
    132 sigchild_action(int signo, siginfo_t *info, void *ptr)
    133 {
    134 	if (info != NULL) {
    135 		printf("info=%p\n", info);
    136 		printf("ptr=%p\n", ptr);
    137 		printf("si_signo=%d\n", info->si_signo);
    138 		printf("si_errno=%d\n", info->si_errno);
    139 		printf("si_code=%d\n", info->si_code);
    140 		printf("si_uid=%d\n", info->si_uid);
    141 		printf("si_pid=%d\n", info->si_pid);
    142 		printf("si_status=%d\n", info->si_status);
    143 		printf("si_utime=%lu\n", (unsigned long int)info->si_utime);
    144 		printf("si_stime=%lu\n", (unsigned long int)info->si_stime);
    145 	}
    146 	ATF_REQUIRE_EQ(info->si_code, code);
    147 	ATF_REQUIRE_EQ(info->si_signo, SIGCHLD);
    148 	ATF_REQUIRE_EQ(info->si_uid, getuid());
    149 	ATF_REQUIRE_EQ(info->si_pid, child);
    150 	if (WIFEXITED(info->si_status))
    151 		ATF_REQUIRE_EQ(WEXITSTATUS(info->si_status), status);
    152 	else if (WIFSTOPPED(info->si_status))
    153 		ATF_REQUIRE_EQ(WSTOPSIG(info->si_status), status);
    154 	else if (WIFSIGNALED(info->si_status))
    155 		ATF_REQUIRE_EQ(WTERMSIG(info->si_status), status);
    156 }
    157 
    158 static void
    159 setchildhandler(void (*action)(int, siginfo_t *, void *))
    160 {
    161 	struct sigaction sa;
    162 	sa.sa_flags = SA_SIGINFO;
    163 	sa.sa_sigaction = action;
    164 	sigemptyset(&sa.sa_mask);
    165 	sigaction(SIGCHLD, &sa, NULL);
    166 }
    167 
    168 static void
    169 sigchild_setup(void)
    170 {
    171 	sigset_t set;
    172 	struct rlimit rlim;
    173 
    174 	(void)getrlimit(RLIMIT_CORE, &rlim);
    175 	rlim.rlim_cur = rlim.rlim_max;
    176 	(void)setrlimit(RLIMIT_CORE, &rlim);
    177 
    178 	setchildhandler(sigchild_action);
    179 	sigemptyset(&set);
    180 	sigaddset(&set, SIGCHLD);
    181 	sigprocmask(SIG_BLOCK, &set, NULL);
    182 }
    183 
    184 ATF_TC(sigchild_normal);
    185 ATF_TC_HEAD(sigchild_normal, tc)
    186 {
    187 
    188 	atf_tc_set_md_var(tc, "descr",
    189 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    190 	    "when child exits normally");
    191 }
    192 
    193 ATF_TC_BODY(sigchild_normal, tc)
    194 {
    195 	sigset_t set;
    196 
    197 	sigchild_setup();
    198 
    199 	status = 25;
    200 	code = CLD_EXITED;
    201 
    202 	switch ((child = fork())) {
    203 	case 0:
    204 		sleep(1);
    205 		exit(status);
    206 	case -1:
    207 		atf_tc_fail("fork failed");
    208 	default:
    209 		sigemptyset(&set);
    210 		sigsuspend(&set);
    211 	}
    212 }
    213 
    214 ATF_TC(sigchild_dump);
    215 ATF_TC_HEAD(sigchild_dump, tc)
    216 {
    217 
    218 	atf_tc_set_md_var(tc, "descr",
    219 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    220 	    "when child segfaults");
    221 }
    222 
    223 ATF_TC_BODY(sigchild_dump, tc)
    224 {
    225 	sigset_t set;
    226 
    227 	sigchild_setup();
    228 
    229 	status = SIGSEGV;
    230 	code = CLD_DUMPED;
    231 
    232 	switch ((child = fork())) {
    233 	case 0:
    234 		sleep(1);
    235 		*(volatile long *)0 = 0;
    236 		atf_tc_fail("Child did not segfault");
    237 		/* NOTREACHED */
    238 	case -1:
    239 		atf_tc_fail("fork failed");
    240 	default:
    241 		sigemptyset(&set);
    242 		sigsuspend(&set);
    243 	}
    244 }
    245 
    246 ATF_TC(sigchild_kill);
    247 ATF_TC_HEAD(sigchild_kill, tc)
    248 {
    249 
    250 	atf_tc_set_md_var(tc, "descr",
    251 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
    252 	    "when child is killed");
    253 }
    254 
    255 ATF_TC_BODY(sigchild_kill, tc)
    256 {
    257 	sigset_t set;
    258 
    259 	sigchild_setup();
    260 
    261 	status = SIGPIPE;
    262 	code = CLD_KILLED;
    263 
    264 	switch ((child = fork())) {
    265 	case 0:
    266 		sigemptyset(&set);
    267 		sigsuspend(&set);
    268 		break;
    269 	case -1:
    270 		atf_tc_fail("fork failed");
    271 	default:
    272 		kill(child, SIGPIPE);
    273 		sigemptyset(&set);
    274 		sigsuspend(&set);
    275 	}
    276 }
    277 
    278 static sigjmp_buf sigfpe_flt_env;
    279 static void
    280 sigfpe_flt_action(int signo, siginfo_t *info, void *ptr)
    281 {
    282 
    283 	sig_debug(signo, info, (ucontext_t *)ptr);
    284 
    285 	if (fltdiv_signalled++ != 0)
    286 		atf_tc_fail("FPE handler called more than once");
    287 
    288 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
    289 	ATF_REQUIRE_EQ(info->si_code, FPE_FLTDIV);
    290 	ATF_REQUIRE_EQ(info->si_errno, 0);
    291 
    292 	siglongjmp(sigfpe_flt_env, 1);
    293 }
    294 
    295 ATF_TC(sigfpe_flt);
    296 ATF_TC_HEAD(sigfpe_flt, tc)
    297 {
    298 
    299 	atf_tc_set_md_var(tc, "descr",
    300 	    "Checks that signal trampoline correctly calls SIGFPE handler "
    301 	    "for floating div-by-zero");
    302 }
    303 
    304 ATF_TC_BODY(sigfpe_flt, tc)
    305 {
    306 	struct sigaction sa;
    307 	double d = strtod("0", NULL);
    308 
    309 	if (isQEMU())
    310 		atf_tc_skip("Test does not run correctly under QEMU");
    311 #if defined(__powerpc__)
    312 	atf_tc_skip("Test not valid on powerpc");
    313 #endif
    314 	if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
    315 		sa.sa_flags = SA_SIGINFO;
    316 		sa.sa_sigaction = sigfpe_flt_action;
    317 		sigemptyset(&sa.sa_mask);
    318 		sigaction(SIGFPE, &sa, NULL);
    319 #ifdef HAVE_FENV
    320 		feenableexcept(FE_ALL_EXCEPT);
    321 #elif defined(_FLOAT_IEEE754)
    322 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
    323 #endif
    324 		printf("%g\n", 1 / d);
    325 	}
    326 	if (fltdiv_signalled == 0)
    327 		atf_tc_fail("FPE signal handler was not invoked");
    328 }
    329 
    330 static sigjmp_buf sigfpe_int_env;
    331 static void
    332 sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
    333 {
    334 
    335 	sig_debug(signo, info, (ucontext_t *)ptr);
    336 
    337 	if (intdiv_signalled++ != 0)
    338 		atf_tc_fail("INTDIV handler called more than once");
    339 
    340 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
    341 	ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
    342 	atf_tc_expect_pass();
    343 	ATF_REQUIRE_EQ(info->si_errno, 0);
    344 
    345 	siglongjmp(sigfpe_int_env, 1);
    346 }
    347 
    348 ATF_TC(sigfpe_int);
    349 ATF_TC_HEAD(sigfpe_int, tc)
    350 {
    351 
    352 	atf_tc_set_md_var(tc, "descr",
    353 	    "Checks that signal trampoline correctly calls SIGFPE handler "
    354 	    "for integer div-by-zero (PR port-i386/43655)");
    355 }
    356 
    357 ATF_TC_BODY(sigfpe_int, tc)
    358 {
    359 	struct sigaction sa;
    360 	long l = strtol("0", NULL, 10);
    361 
    362 #if defined(__powerpc__)
    363 	atf_tc_skip("Test not valid on powerpc");
    364 #endif
    365 	if (sigsetjmp(sigfpe_int_env, 0) == 0) {
    366 		sa.sa_flags = SA_SIGINFO;
    367 		sa.sa_sigaction = sigfpe_int_action;
    368 		sigemptyset(&sa.sa_mask);
    369 		sigaction(SIGFPE, &sa, NULL);
    370 #ifdef HAVE_FENV
    371 		feenableexcept(FE_ALL_EXCEPT);
    372 #elif defined(_FLOAT_IEEE754)
    373 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
    374 #endif
    375 		printf("%ld\n", 1 / l);
    376 	}
    377 	if (intdiv_signalled == 0)
    378 		atf_tc_fail("FPE signal handler was not invoked");
    379 }
    380 
    381 static void
    382 sigsegv_action(int signo, siginfo_t *info, void *ptr)
    383 {
    384 
    385 	sig_debug(signo, info, (ucontext_t *)ptr);
    386 
    387 	ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
    388 	ATF_REQUIRE_EQ(info->si_errno, 0);
    389 	ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
    390 	ATF_REQUIRE_EQ(info->si_addr, (void *)0);
    391 
    392 	atf_tc_pass();
    393 	/* NOTREACHED */
    394 }
    395 
    396 ATF_TC(sigsegv);
    397 ATF_TC_HEAD(sigsegv, tc)
    398 {
    399 
    400 	atf_tc_set_md_var(tc, "descr",
    401 	    "Checks that signal trampoline correctly calls SIGSEGV handler");
    402 }
    403 
    404 ATF_TC_BODY(sigsegv, tc)
    405 {
    406 	struct sigaction sa;
    407 
    408 	sa.sa_flags = SA_SIGINFO;
    409 	sa.sa_sigaction = sigsegv_action;
    410 	sigemptyset(&sa.sa_mask);
    411 	sigaction(SIGSEGV, &sa, NULL);
    412 
    413 	*(volatile long *)0 = 0;
    414 	atf_tc_fail("Test did not fault as expected");
    415 }
    416 
    417 static void
    418 sigbus_action(int signo, siginfo_t *info, void *ptr)
    419 {
    420 
    421 	printf("si_addr = %p\n", info->si_addr);
    422 	sig_debug(signo, info, (ucontext_t *)ptr);
    423 
    424 	ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
    425 	ATF_REQUIRE_EQ(info->si_errno, 0);
    426 	ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
    427 
    428 #if defined(__i386__) || defined(__x86_64__)
    429 	atf_tc_expect_fail("x86 architecture does not correctly "
    430 	    "report the address where the unaligned access occured");
    431 #endif
    432 	ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
    433 
    434 	atf_tc_pass();
    435 	/* NOTREACHED */
    436 }
    437 
    438 ATF_TC(sigbus_adraln);
    439 ATF_TC_HEAD(sigbus_adraln, tc)
    440 {
    441 
    442 	atf_tc_set_md_var(tc, "descr",
    443 	    "Checks that signal trampoline correctly calls SIGBUS handler "
    444 	    "for invalid address alignment");
    445 }
    446 
    447 ATF_TC_BODY(sigbus_adraln, tc)
    448 {
    449 	struct sigaction sa;
    450 
    451 #if defined(__alpha__)
    452 	int rv, val;
    453 	size_t len = sizeof(val);
    454 	rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
    455 	ATF_REQUIRE(rv == 0);
    456 	if (val == 0)
    457 		atf_tc_skip("SIGBUS signal not enabled for unaligned accesses");
    458 #endif
    459 
    460 	sa.sa_flags = SA_SIGINFO;
    461 	sa.sa_sigaction = sigbus_action;
    462 	sigemptyset(&sa.sa_mask);
    463 	sigaction(SIGBUS, &sa, NULL);
    464 
    465 	/* Enable alignment checks for x86. 0x40000 is PSL_AC. */
    466 #if defined(__i386__)
    467 	__asm__("pushf; orl $0x40000, (%esp); popf");
    468 #elif defined(__amd64__)
    469 	__asm__("pushf; orl $0x40000, (%rsp); popf");
    470 #endif
    471 
    472 	addr = calloc(2, sizeof(int));
    473 	ATF_REQUIRE(addr != NULL);
    474 
    475 	if (isQEMU())
    476 		atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
    477 
    478 	/* Force an unaligned access */
    479 	addr++;
    480 	printf("now trying to access unaligned address %p\n", addr);
    481 	ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
    482 
    483 	atf_tc_fail("Test did not fault as expected");
    484 }
    485 
    486 ATF_TP_ADD_TCS(tp)
    487 {
    488 
    489 	ATF_TP_ADD_TC(tp, sigalarm);
    490 	ATF_TP_ADD_TC(tp, sigchild_normal);
    491 	ATF_TP_ADD_TC(tp, sigchild_dump);
    492 	ATF_TP_ADD_TC(tp, sigchild_kill);
    493 	ATF_TP_ADD_TC(tp, sigfpe_flt);
    494 	ATF_TP_ADD_TC(tp, sigfpe_int);
    495 	ATF_TP_ADD_TC(tp, sigsegv);
    496 	ATF_TP_ADD_TC(tp, sigbus_adraln);
    497 
    498 	return atf_no_error();
    499 }
    500