1/* $NetBSD: t_signal_and_sp.c,v 1.1 2024/04/22 07:24:22 pho 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#include <atf-c.h> 30 31#if defined(HAVE_STACK_POINTER_H) 32# include <signal.h> 33# include <string.h> 34# include <sys/stdint.h> 35# include <sys/time.h> 36# include "stack_pointer.h" 37 38static volatile void* stack_pointer = NULL; 39static void on_alarm(int sig __attribute__((__unused__))) 40{ 41 /* 42 * Store the stack pointer into a variable so that we can test if 43 * it's aligned. 44 */ 45 LOAD_SP(stack_pointer); 46 47 /* 48 * Now we are going to return from a signal 49 * handler. __sigtramp_siginfo_2 will call setcontext(2) with a 50 * ucontext provided by the kernel. When that fails it will call 51 * _Exit(2) with the errno, and the test will fail. 52 */ 53} 54#endif 55 56ATF_TC(misaligned_sp_and_signal); 57ATF_TC_HEAD(misaligned_sp_and_signal, tc) 58{ 59 atf_tc_set_md_var(tc, "descr", "process can return from a signal" 60 " handler even if the stack pointer is misaligned when a signal" 61 " arrives"); 62} 63ATF_TC_BODY(misaligned_sp_and_signal, tc) 64{ 65#if defined(HAVE_STACK_POINTER_H) 66 /* 67 * Set up a handler for SIGALRM. 68 */ 69 struct sigaction sa; 70 memset(&sa, 0, sizeof(sa)); 71 sa.sa_handler = &on_alarm; 72 ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0); 73 74 /* 75 * Set up an interval timer so that we receive SIGALRM after 50 ms. 76 */ 77 struct itimerval itv; 78 memset(&itv, 0, sizeof(itv)); 79 itv.it_value.tv_usec = 1000 * 50; 80 ATF_REQUIRE(setitimer(ITIMER_MONOTONIC, &itv, NULL) == 0); 81 82 /* 83 * Now misalign the SP. Wait for the signal to arrive and see what 84 * happens. This should be fine as long as we don't use it to 85 * access memory. 86 */ 87 MISALIGN_SP; 88 while (stack_pointer == NULL) { 89 /* 90 * Make sure the compiler does not optimize this busy loop 91 * away. 92 */ 93 __asm__("" : : : "memory"); 94 } 95 /* 96 * We could successfully return from a signal handler. Now we 97 * should fix the SP before calling any functions. 98 */ 99 FIX_SP; 100 101 /* 102 * But was the stack pointer aligned when we were on the signal 103 * handler? 104 */ 105 ATF_CHECK_MSG(is_sp_aligned((uintptr_t)stack_pointer), 106 "signal handler was called with a misaligned sp: %p", 107 stack_pointer); 108#else 109 atf_tc_skip("Not implemented for this platform"); 110#endif 111} 112 113ATF_TP_ADD_TCS(tp) 114{ 115 ATF_TP_ADD_TC(tp, misaligned_sp_and_signal); 116 return atf_no_error(); 117} 118