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