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#ifdef __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 */ 58volatile char *addr; 59 60/* for sigchild */ 61pid_t child; 62int code; 63int status; 64 65/* for sigfpe */ 66sig_atomic_t fltdiv_signalled = 0; 67sig_atomic_t intdiv_signalled = 0; 68 69static void 70sig_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#ifdef __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 98static void 99sigalrm_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 112ATF_TC(sigalarm); 113 114ATF_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 121ATF_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 135static void 136sigchild_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#ifdef __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 164static void 165setchildhandler(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 174static void 175sigchild_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 190ATF_TC(sigchild_normal); 191ATF_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 199ATF_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 220ATF_TC(sigchild_dump); 221ATF_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 229ATF_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 252ATF_TC(sigchild_kill); 253ATF_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 261ATF_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 284static sigjmp_buf sigfpe_flt_env; 285static void 286sigfpe_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 301ATF_TC(sigfpe_flt); 302ATF_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 310ATF_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 336static sigjmp_buf sigfpe_int_env; 337static void 338sigfpe_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 354ATF_TC(sigfpe_int); 355ATF_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 363ATF_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 387static void 388sigsegv_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 402ATF_TC(sigsegv); 403ATF_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 410ATF_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 423static void 424sigbus_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 444ATF_TC(sigbus_adraln); 445ATF_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 453ATF_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 492ATF_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