1 /* $NetBSD: t_signal_and_sp.c,v 1.21 2025/04/26 23:49:55 uwe Exp $ */ 2 3 /* 4 * Copyright (c) 2024 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 #define __EXPOSE_STACK /* <sys/param.h>: expose STACK_ALIGNBYTES */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: t_signal_and_sp.c,v 1.21 2025/04/26 23:49:55 uwe Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/wait.h> 36 37 #include <atf-c.h> 38 #include <limits.h> 39 #include <poll.h> 40 #include <pthread.h> 41 #include <signal.h> 42 #include <stdint.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <time.h> 47 #include <ucontext.h> 48 #include <unistd.h> 49 50 #include "h_execsp.h" 51 #include "h_macros.h" 52 53 #ifdef HAVE_STACK_POINTER_H 54 # include "stack_pointer.h" 55 #endif 56 57 #define PR_59327 "PR kern/59327: user stack pointer is not aligned properly" 58 59 #ifdef HAVE_SIGNALSPHANDLER 60 void signalsphandler(int); /* signalsphandler.S assembly routine */ 61 #endif 62 63 void *volatile signalsp; 64 65 static void 66 test_execsp(const struct atf_tc *tc, const char *prog) 67 { 68 #ifdef STACK_ALIGNBYTES 69 char h_execsp[PATH_MAX]; 70 struct execsp execsp; 71 int fd[2]; 72 pid_t pid; 73 struct pollfd pollfd; 74 int nfds; 75 ssize_t nread; 76 int status; 77 78 /* 79 * Determine the full path to the helper program. 80 */ 81 RL(snprintf(h_execsp, sizeof(h_execsp), "%s/%s", 82 atf_tc_get_config_var(tc, "srcdir"), prog)); 83 84 /* 85 * Create a pipe to read a bundle of stack pointer samples from 86 * the child, and fork the child. 87 */ 88 RL(pipe(fd)); 89 RL(pid = vfork()); 90 if (pid == 0) { /* child */ 91 char *const argv[] = {h_execsp, NULL}; 92 93 if (dup2(fd[1], STDOUT_FILENO) == -1) 94 _exit(1); 95 if (closefrom(STDERR_FILENO + 1) == -1) 96 _exit(2); 97 if (execve(argv[0], argv, NULL) == -1) 98 _exit(3); 99 _exit(4); 100 } 101 102 /* 103 * Close the writing end so, if something goes wrong in the 104 * child, we don't hang indefinitely waiting for output. 105 */ 106 RL(close(fd[1])); 107 108 /* 109 * Wait up to 5sec for the child to return an answer. Any more 110 * than that, and we kill it. The child is mostly hand-written 111 * assembly routines where lots can go wrong, so don't bother 112 * waiting if it gets stuck in a loop. 113 */ 114 pollfd.fd = fd[0]; 115 pollfd.events = POLLIN; 116 RL(nfds = poll(&pollfd, 1, 5*1000/*ms*/)); 117 if (nfds == 0) { 118 fprintf(stderr, "child hung, killing\n"); 119 RL(kill(pid, SIGKILL)); 120 } 121 122 /* 123 * Read a bundle of stack pointer samples from the child. 124 */ 125 RL(nread = read(fd[0], &execsp, sizeof(execsp))); 126 ATF_CHECK_MSG((size_t)nread == sizeof(execsp), 127 "nread=%zu sizeof(execsp)=%zu", 128 (size_t)nread, sizeof(execsp)); 129 130 /* 131 * Wait for the child to terminate and report failure if it 132 * didn't exit cleanly. 133 */ 134 RL(waitpid(pid, &status, 0)); 135 if (WIFSIGNALED(status)) { 136 atf_tc_fail_nonfatal("child exited on signal %d (%s)", 137 WTERMSIG(status), strsignal(WTERMSIG(status))); 138 } else if (!WIFEXITED(status)) { 139 atf_tc_fail_nonfatal("child exited status=0x%x", status); 140 } else { 141 ATF_CHECK_MSG(WEXITSTATUS(status) == 0, 142 "child exited with code %d", 143 WEXITSTATUS(status)); 144 } 145 146 /* 147 * Now that we have reaped the child, stop here if the stack 148 * pointer samples are bogus; otherwise verify they are all 149 * aligned. 150 */ 151 if ((size_t)nread != sizeof(execsp)) 152 return; /* failed already */ 153 154 printf("start sp @ %p\n", execsp.startsp); 155 printf("ctor sp @ %p\n", execsp.ctorsp); 156 printf("main sp @ %p\n", execsp.mainsp); 157 printf("dtor sp @ %p\n", execsp.dtorsp); 158 159 ATF_CHECK_MSG(((uintptr_t)execsp.startsp & STACK_ALIGNBYTES) == 0, 160 "elf entry point was called with misaligned sp: %p", 161 execsp.startsp); 162 163 ATF_CHECK_MSG(((uintptr_t)execsp.ctorsp & STACK_ALIGNBYTES) == 0, 164 "elf constructor was called with misaligned sp: %p", 165 execsp.ctorsp); 166 167 ATF_CHECK_MSG(((uintptr_t)execsp.mainsp & STACK_ALIGNBYTES) == 0, 168 "main function was called with misaligned sp: %p", 169 execsp.mainsp); 170 171 ATF_CHECK_MSG(((uintptr_t)execsp.dtorsp & STACK_ALIGNBYTES) == 0, 172 "elf destructor was called with misaligned sp: %p", 173 execsp.dtorsp); 174 175 /* 176 * Leave a reminder on architectures for which we haven't 177 * implemented execsp_start.S. 178 */ 179 if (execsp.startsp == NULL || 180 execsp.ctorsp == NULL || 181 execsp.mainsp == NULL || 182 execsp.dtorsp == NULL) 183 atf_tc_skip("Not fully supported on this architecture"); 184 #else 185 atf_tc_skip("Unknown STACK_ALIGNBYTES on this architecture"); 186 #endif 187 } 188 189 ATF_TC(execsp_dynamic); 190 ATF_TC_HEAD(execsp_dynamic, tc) 191 { 192 atf_tc_set_md_var(tc, "descr", 193 "Verify stack pointer is aligned on dynamic program start"); 194 } 195 ATF_TC_BODY(execsp_dynamic, tc) 196 { 197 test_execsp(tc, "h_execsp_dynamic"); 198 } 199 200 ATF_TC(execsp_static); 201 ATF_TC_HEAD(execsp_static, tc) 202 { 203 atf_tc_set_md_var(tc, "descr", 204 "Verify stack pointer is aligned on static program start"); 205 } 206 ATF_TC_BODY(execsp_static, tc) 207 { 208 test_execsp(tc, "h_execsp_static"); 209 } 210 211 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC 212 void *volatile contextsp; /* set by contextspfunc.S */ 213 static ucontext_t return_context; 214 static volatile bool test_context_done; 215 216 void contextspfunc(void); /* contextspfunc.S assembly routine */ 217 218 static void 219 contextnoop(void) 220 { 221 222 fprintf(stderr, "contextnoop\n"); 223 /* control will return to contextspfunc via uc_link */ 224 } 225 226 void contextdone(void); /* called by contextspfunc.S */ 227 void 228 contextdone(void) 229 { 230 231 fprintf(stderr, "contextdone\n"); 232 ATF_REQUIRE(!test_context_done); 233 test_context_done = true; 234 RL(setcontext(&return_context)); 235 atf_tc_fail("setcontext returned"); 236 } 237 #endif 238 239 ATF_TC(contextsp); 240 ATF_TC_HEAD(contextsp, tc) 241 { 242 atf_tc_set_md_var(tc, "descr", 243 "Verify stack pointer is aligned on makecontext entry"); 244 } 245 ATF_TC_BODY(contextsp, tc) 246 { 247 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC 248 ucontext_t uc; 249 char *stack; 250 unsigned i; 251 252 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL); 253 fprintf(stderr, "stack @ [%p,%p)\n", stack, 254 stack + SIGSTKSZ + STACK_ALIGNBYTES); 255 256 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 257 contextsp = NULL; 258 test_context_done = false; 259 260 RL(getcontext(&uc)); 261 uc.uc_stack.ss_sp = stack; 262 uc.uc_stack.ss_size = SIGSTKSZ + i; 263 makecontext(&uc, &contextspfunc, 0); 264 265 fprintf(stderr, "[%u] swapcontext\n", i); 266 RL(swapcontext(&return_context, &uc)); 267 268 ATF_CHECK(contextsp != NULL); 269 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)contextsp && 270 (uintptr_t)contextsp <= (uintptr_t)stack + SIGSTKSZ + i, 271 "contextsp=%p", contextsp); 272 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0, 273 "[%u] makecontext function called with misaligned sp %p", 274 i, contextsp); 275 } 276 277 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 278 contextsp = NULL; 279 test_context_done = false; 280 281 RL(getcontext(&uc)); 282 uc.uc_stack.ss_sp = stack + i; 283 uc.uc_stack.ss_size = SIGSTKSZ; 284 makecontext(&uc, &contextspfunc, 0); 285 286 fprintf(stderr, "[%u] swapcontext\n", i); 287 RL(swapcontext(&return_context, &uc)); 288 289 ATF_CHECK(contextsp != NULL); 290 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)contextsp && 291 (uintptr_t)contextsp <= (uintptr_t)stack + i + SIGSTKSZ, 292 "contextsp=%p", contextsp); 293 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0, 294 "[%u] makecontext function called with misaligned sp %p", 295 i, contextsp); 296 } 297 #else 298 atf_tc_skip("Not implemented on this platform"); 299 #endif 300 } 301 302 ATF_TC(contextsplink); 303 ATF_TC_HEAD(contextsplink, tc) 304 { 305 atf_tc_set_md_var(tc, "descr", 306 "Verify stack pointer is aligned on makecontext link entry"); 307 } 308 ATF_TC_BODY(contextsplink, tc) 309 { 310 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC 311 ucontext_t uc1, uc2; 312 char *stack1, *stack2; 313 unsigned i; 314 315 REQUIRE_LIBC(stack1 = malloc(SIGSTKSZ), NULL); 316 fprintf(stderr, "stack1 @ [%p,%p)\n", stack1, stack1 + SIGSTKSZ); 317 REQUIRE_LIBC(stack2 = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL); 318 fprintf(stderr, "stack2 @ [%p,%p)\n", 319 stack2, stack2 + SIGSTKSZ + STACK_ALIGNBYTES); 320 321 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 322 contextsp = NULL; 323 test_context_done = false; 324 325 RL(getcontext(&uc1)); 326 uc1.uc_stack.ss_sp = stack1; 327 uc1.uc_stack.ss_size = SIGSTKSZ; 328 uc1.uc_link = &uc2; 329 makecontext(&uc1, &contextnoop, 0); 330 331 RL(getcontext(&uc2)); 332 uc2.uc_stack.ss_sp = stack2; 333 uc2.uc_stack.ss_size = SIGSTKSZ + i; 334 makecontext(&uc2, &contextspfunc, 0); 335 336 fprintf(stderr, "[%u] swapcontext\n", i); 337 RL(swapcontext(&return_context, &uc1)); 338 339 ATF_CHECK(contextsp != NULL); 340 ATF_CHECK_MSG((uintptr_t)stack2 <= (uintptr_t)contextsp && 341 (uintptr_t)contextsp <= (uintptr_t)stack2 + SIGSTKSZ + i, 342 "contextsp=%p", contextsp); 343 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0, 344 "[%u] makecontext function called with misaligned sp %p", 345 i, contextsp); 346 } 347 348 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 349 contextsp = NULL; 350 test_context_done = false; 351 352 RL(getcontext(&uc1)); 353 uc1.uc_stack.ss_sp = stack1; 354 uc1.uc_stack.ss_size = SIGSTKSZ; 355 uc1.uc_link = &uc2; 356 makecontext(&uc1, &contextnoop, 0); 357 358 RL(getcontext(&uc2)); 359 uc2.uc_stack.ss_sp = stack2 + i; 360 uc2.uc_stack.ss_size = SIGSTKSZ; 361 makecontext(&uc2, &contextspfunc, 0); 362 363 fprintf(stderr, "[%u] swapcontext\n", i); 364 RL(swapcontext(&return_context, &uc1)); 365 366 ATF_CHECK(contextsp != NULL); 367 ATF_CHECK_MSG((uintptr_t)stack2 + i <= (uintptr_t)contextsp && 368 (uintptr_t)contextsp <= (uintptr_t)stack2 + SIGSTKSZ + i, 369 "contextsp=%p", contextsp); 370 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0, 371 "[%u] makecontext function called with misaligned sp %p", 372 i, contextsp); 373 } 374 #else 375 atf_tc_skip("Not implemented on this platform"); 376 #endif 377 } 378 379 ATF_TC(signalsp); 380 ATF_TC_HEAD(signalsp, tc) 381 { 382 atf_tc_set_md_var(tc, "descr", 383 "Verify stack pointer is aligned on entry to signal handler"); 384 } 385 ATF_TC_BODY(signalsp, tc) 386 { 387 #if defined STACK_ALIGNBYTES && defined HAVE_SIGNALSPHANDLER 388 struct sigaction sa; 389 390 memset(&sa, 0, sizeof(sa)); 391 sa.sa_handler = &signalsphandler; 392 RL(sigaction(SIGUSR1, &sa, NULL)); 393 RL(raise(SIGUSR1)); 394 395 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0, 396 "signal handler was called with a misaligned sp: %p", 397 signalsp); 398 #else 399 atf_tc_skip("Not implemented on this platform"); 400 #endif 401 } 402 403 ATF_TC(signalsp_sigaltstack); 404 ATF_TC_HEAD(signalsp_sigaltstack, tc) 405 { 406 atf_tc_set_md_var(tc, "descr", 407 "Verify stack pointer is aligned on entry to signal handler" 408 " with maximally misaligned sigaltstack"); 409 } 410 ATF_TC_BODY(signalsp_sigaltstack, tc) 411 { 412 #if defined STACK_ALIGNBYTES && HAVE_SIGNALSPHANDLER 413 #if defined(__sh__) 414 atf_tc_expect_fail(PR_59327); 415 #endif 416 char *stack; 417 struct sigaction sa; 418 struct sigaltstack ss; 419 unsigned i; 420 421 memset(&sa, 0, sizeof(sa)); 422 sa.sa_handler = &signalsphandler; 423 sa.sa_flags = SA_ONSTACK; 424 RL(sigaction(SIGUSR1, &sa, NULL)); 425 426 /* 427 * Allocate a signal stack with enough slop to try all possible 428 * misalignments of the stack pointer. Print it to stderr so 429 * it always appears in atf output before shenanigans happen. 430 */ 431 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL); 432 fprintf(stderr, "stack @ [%p, %p)\n", 433 stack, stack + SIGSTKSZ + STACK_ALIGNBYTES); 434 435 /* 436 * Try with all alignments of high addresses. 437 */ 438 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 439 ss.ss_sp = stack; 440 ss.ss_size = SIGSTKSZ + i; 441 ss.ss_flags = 0; 442 RL(sigaltstack(&ss, NULL)); 443 444 signalsp = NULL; 445 RL(raise(SIGUSR1)); 446 ATF_CHECK(signalsp != NULL); 447 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)signalsp && 448 (uintptr_t)signalsp <= (uintptr_t)stack + SIGSTKSZ + i, 449 "signalsp=%p", signalsp); 450 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0, 451 "[%u] signal handler was called with a misaligned sp: %p", 452 i, signalsp); 453 } 454 455 /* 456 * Try with all alignments of low addresses. 457 */ 458 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 459 ss.ss_sp = stack + i; 460 ss.ss_size = SIGSTKSZ; 461 ss.ss_flags = 0; 462 RL(sigaltstack(&ss, NULL)); 463 464 signalsp = NULL; 465 RL(raise(SIGUSR1)); 466 ATF_CHECK(signalsp != NULL); 467 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)signalsp && 468 (uintptr_t)signalsp <= (uintptr_t)stack + i + SIGSTKSZ, 469 "signalsp=%p", signalsp); 470 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0, 471 "[%u] signal handler was called with a misaligned sp: %p", 472 i, signalsp); 473 } 474 #else 475 atf_tc_skip("Not implemented on this platform"); 476 #endif 477 } 478 479 #if defined STACK_ALIGNBYTES && defined HAVE_THREADSPFUNC 480 void *threadspfunc(void *); /* threadspfunc.S assembly routine */ 481 #endif 482 483 ATF_TC(threadsp); 484 ATF_TC_HEAD(threadsp, tc) 485 { 486 atf_tc_set_md_var(tc, "descr", 487 "Verify stack pointer is aligned on thread start"); 488 } 489 ATF_TC_BODY(threadsp, tc) 490 { 491 #if defined STACK_ALIGNBYTES && defined HAVE_THREADSPFUNC 492 pthread_t t; 493 void *sp; 494 char *stack; 495 unsigned i; 496 497 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL); 498 fprintf(stderr, "stack @ [%p,%p)\n", stack, 499 stack + SIGSTKSZ + STACK_ALIGNBYTES); 500 501 RZ(pthread_create(&t, NULL, &threadspfunc, NULL)); 502 503 alarm(1); 504 RZ(pthread_join(t, &sp)); 505 alarm(0); 506 507 ATF_CHECK(sp != NULL); 508 ATF_CHECK_MSG(((uintptr_t)sp & STACK_ALIGNBYTES) == 0, 509 "thread called with misaligned sp: %p", sp); 510 511 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 512 pthread_attr_t attr; 513 514 RZ(pthread_attr_init(&attr)); 515 RZ(pthread_attr_setstack(&attr, stack, SIGSTKSZ + i)); 516 RZ(pthread_create(&t, &attr, &threadspfunc, NULL)); 517 RZ(pthread_attr_destroy(&attr)); 518 519 alarm(1); 520 RZ(pthread_join(t, &sp)); 521 alarm(0); 522 523 ATF_CHECK(sp != NULL); 524 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)sp && 525 (uintptr_t)sp <= (uintptr_t)stack + SIGSTKSZ + i, 526 "sp=%p", sp); 527 ATF_CHECK_MSG(((uintptr_t)sp & STACK_ALIGNBYTES) == 0, 528 "[%u] thread called with misaligned sp: %p", i, sp); 529 } 530 531 for (i = 0; i <= STACK_ALIGNBYTES; i++) { 532 pthread_attr_t attr; 533 534 RZ(pthread_attr_init(&attr)); 535 RZ(pthread_attr_setstack(&attr, stack + i, SIGSTKSZ)); 536 RZ(pthread_create(&t, &attr, &threadspfunc, NULL)); 537 RZ(pthread_attr_destroy(&attr)); 538 539 alarm(1); 540 RZ(pthread_join(t, &sp)); 541 alarm(0); 542 543 ATF_CHECK(sp != NULL); 544 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)sp && 545 (uintptr_t)sp <= (uintptr_t)stack + i + SIGSTKSZ, 546 "sp=%p", sp); 547 ATF_CHECK_MSG(((uintptr_t)sp & STACK_ALIGNBYTES) == 0, 548 "[%u] thread called with misaligned sp: %p", i, sp); 549 } 550 #else 551 atf_tc_skip("Not implemented on this platform"); 552 #endif 553 } 554 555 ATF_TC(misaligned_sp_and_signal); 556 ATF_TC_HEAD(misaligned_sp_and_signal, tc) 557 { 558 atf_tc_set_md_var(tc, "descr", "process can return from a signal" 559 " handler even if the stack pointer is misaligned when a signal" 560 " arrives"); 561 } 562 ATF_TC_BODY(misaligned_sp_and_signal, tc) 563 { 564 #if defined STACK_ALIGNBYTES && defined HAVE_STACK_POINTER_H 565 #if defined(__sh__) 566 atf_tc_expect_fail(PR_59327); 567 #endif 568 569 /* 570 * Set up a handler for SIGALRM. 571 */ 572 struct sigaction sa; 573 memset(&sa, 0, sizeof(sa)); 574 sa.sa_handler = &signalsphandler; 575 RL(sigaction(SIGALRM, &sa, NULL)); 576 577 /* 578 * Set up an interval timer so that we receive SIGALRM after 50 ms. 579 */ 580 struct itimerval itv; 581 memset(&itv, 0, sizeof(itv)); 582 itv.it_value.tv_usec = 1000 * 50; 583 RL(setitimer(ITIMER_MONOTONIC, &itv, NULL)); 584 585 /* 586 * Now misalign the SP. Wait for the signal to arrive and see what 587 * happens. This should be fine as long as we don't use it to 588 * access memory. 589 */ 590 MISALIGN_SP; 591 while (signalsp == NULL) { 592 /* 593 * Make sure the compiler does not optimize this busy loop 594 * away. 595 */ 596 __asm__("" ::: "memory"); 597 } 598 /* 599 * We could successfully return from a signal handler. Now we 600 * should fix the SP before calling any functions. 601 */ 602 FIX_SP; 603 604 /* 605 * But was the stack pointer aligned when we were on the signal 606 * handler? 607 */ 608 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0, 609 "signal handler was called with a misaligned sp: %p", 610 signalsp); 611 #else 612 atf_tc_skip("Not implemented for this platform"); 613 #endif 614 } 615 616 ATF_TP_ADD_TCS(tp) 617 { 618 619 ATF_TP_ADD_TC(tp, contextsp); 620 ATF_TP_ADD_TC(tp, contextsplink); 621 ATF_TP_ADD_TC(tp, execsp_dynamic); 622 ATF_TP_ADD_TC(tp, execsp_static); 623 ATF_TP_ADD_TC(tp, misaligned_sp_and_signal); 624 ATF_TP_ADD_TC(tp, signalsp); 625 ATF_TP_ADD_TC(tp, signalsp_sigaltstack); 626 ATF_TP_ADD_TC(tp, threadsp); 627 return atf_no_error(); 628 } 629