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