• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * Copyright (c) 2009 Cisco Systems, Inc.  All Rights Reserved.
4   * Copyright (c) 2009 FUJITSU LIMITED.  All Rights Reserved.
5   * Author: Liu Bo <liubo2009@cn.fujitsu.com>
6   * Author: Ngie Cooper <yaneurabeya@gmail.com>
7   */
8  
9  #ifndef LAPI_RT_SIGACTION_H__
10  #define LAPI_RT_SIGACTION_H__
11  
12  #include "ltp_signal.h"
13  
14  #define INVAL_SA_PTR ((void *)-1)
15  
16  #if defined(__mips__)
17  struct kernel_sigaction {
18  	unsigned int sa_flags;
19  	void (* k_sa_handler)(int);
20  	sigset_t sa_mask;
21  };
22  #else
23  struct kernel_sigaction {
24  	void (* k_sa_handler)(int);
25  	unsigned long sa_flags;
26  	void (*sa_restorer) (void);
27  	sigset_t sa_mask;
28  };
29  #endif
30  
31  /* This macro marks if (struct sigaction) has .sa_restorer member */
32  #if !defined(__ia64__) && !defined(__alpha__) && !defined(__hppa__) && !defined(__mips__)
33  # define HAVE_SA_RESTORER
34  #endif
35  
36  #ifdef __x86_64__
37  
38  /*
39   * From asm/signal.h -- this value isn't exported anywhere outside of glibc and
40   * asm/signal.h and is only required for the rt_sig* function family because
41   * sigaction(2), et all, appends this if necessary to
42   * (struct sigaction).sa_flags. HEH.
43   *
44   * I do #undef though, just in case...
45   *
46   * Also, from .../arch/x86/kernel/signal.c:448 for v2.6.30 (something or
47   * other):
48   *
49   * x86-64 should always use SA_RESTORER.
50   *
51   * -- thus SA_RESTORER must always be defined along with
52   * (struct sigaction).sa_restorer for this architecture.
53   */
54  #undef SA_RESTORER
55  #define SA_RESTORER     0x04000000
56  
57  void (*restore_rt)(void);
58  
handler_h(int signal)59  static void handler_h(int signal)
60  {
61  	return;
62  }
63  
64  /* Setup an initial signal handler for signal number = sig for x86_64. */
sig_initial(int sig)65  static inline int sig_initial(int sig)
66  {
67  	int ret_code = -1;
68  	struct sigaction act, oact;
69  
70  	act.sa_handler = handler_h;
71  	act.sa_flags = 0;
72  	/* Clear out the signal set. */
73  	if (sigemptyset(&act.sa_mask) < 0) {
74  		/* Add the signal to the mask set. */
75  	} else if (sigaddset(&act.sa_mask, sig) < 0) {
76  		/* Set act.sa_restorer via syscall(2) */
77  	} else if (sigaction(sig, &act, &oact) < 0) {
78  		/* Copy oact.sa_restorer via syscall(2) */
79  	} else if (sigaction(sig, &act, &oact) < 0) {
80  		/* And voila -- we just tricked the kernel into giving us our
81  		 * restorer function! */
82  	} else {
83  		restore_rt = oact.sa_restorer;
84  		ret_code = 0;
85  	}
86  
87  	return ret_code;
88  }
89  
90  #endif /* __x86_64__ */
91  
92  #ifdef __sparc__
93  # if defined __arch64__ || defined __sparcv9
94  
95  /*
96   * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
97   */
98  
99  extern char *__rt_sig_stub;
100  
__rt_sigreturn_stub(void)101  static void __attribute__((used)) __rt_sigreturn_stub(void)
102  {
103  	__asm__ ("__rt_sig_stub: mov %0, %%g1\n\t"
104  		"ta  0x6d\n\t"
105  		: /* no outputs */
106  		: "i" (__NR_rt_sigreturn));
107  }
108  
109  # else /* sparc32 */
110  
111  /*
112   * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
113   */
114  
115  extern char *__rt_sig_stub, *__sig_stub;
116  
__rt_sigreturn_stub(void)117  static void __attribute__((used)) __rt_sigreturn_stub(void)
118  {
119  	__asm__ ("__rt_sig_stub: mov %0, %%g1\n\t"
120  		"ta  0x10\n\t"
121  		: /* no outputs */
122  		: "i" (__NR_rt_sigreturn));
123  }
124  
__sigreturn_stub(void)125  static void __attribute__((used)) __sigreturn_stub(void)
126  {
127  	__asm__ ("__sig_stub: mov %0, %%g1\n\t"
128  		"ta  0x10\n\t"
129  		: /* no outputs */
130  		: "i" (__NR_sigreturn));
131  }
132  
133  # endif
134  #endif /* __sparc__ */
135  
136  #ifdef __arc__
137  
138  #undef SA_RESTORER
139  #define SA_RESTORER     0x04000000
140  
141  /*
142   * based on uClibc/libc/sysdeps/linux/arc/sigaction.c
143   */
144  static void
restore_rt(void)145  __attribute__ ((optimize("Os"))) __attribute__((used)) restore_rt(void)
146  {
147  	__asm__ (
148  		"mov r8, %0	\n\t"
149  #ifdef __ARCHS__
150  		"trap_s	0	\n\t"
151  #else
152  		"trap0	\n\t"
153  #endif
154  		: /* no outputs */
155  		: "i" (__NR_rt_sigreturn)
156  		: "r8");
157  }
158  #endif
159  
160  #ifdef TST_TEST_H__
161  # define TST_SYSCALL tst_syscall
162  #else
163  # define TST_SYSCALL ltp_syscall
164  #endif
165  
166  /* This is a wrapper for __NR_rt_sigaction syscall.
167   * act/oact values of INVAL_SA_PTR is used to pass
168   * an invalid pointer to syscall(__NR_rt_sigaction)
169   *
170   * Based on glibc/sysdeps/unix/sysv/linux/{...}/sigaction.c
171   */
172  
ltp_rt_sigaction(int signum,const struct sigaction * act,struct sigaction * oact,size_t sigsetsize)173  static int ltp_rt_sigaction(int signum, const struct sigaction *act,
174  			struct sigaction *oact, size_t sigsetsize)
175  {
176  	int ret;
177  	struct kernel_sigaction kact, koact;
178  	struct kernel_sigaction *kact_p = NULL;
179  	struct kernel_sigaction *koact_p = NULL;
180  
181  	if (act == INVAL_SA_PTR) {
182  		kact_p = INVAL_SA_PTR;
183  	} else if (act) {
184  		kact.k_sa_handler = act->sa_handler;
185  		memcpy(&kact.sa_mask, &act->sa_mask, sizeof(sigset_t));
186  		kact.sa_flags = act->sa_flags;
187  #ifndef __mips__
188  		kact.sa_restorer = NULL;
189  #endif
190  		kact_p = &kact;
191  	}
192  
193  	if (oact == INVAL_SA_PTR)
194  		koact_p = INVAL_SA_PTR;
195  	else if (oact)
196  		koact_p = &koact;
197  
198  #ifdef __x86_64__
199  	sig_initial(signum);
200  #endif
201  
202  #if defined __x86_64__ || defined __arc__
203  	kact.sa_flags |= SA_RESTORER;
204  	kact.sa_restorer = restore_rt;
205  #endif
206  
207  #ifdef __sparc__
208  	unsigned long stub = 0;
209  # if defined __arch64__ || defined __sparcv9
210  	stub = ((unsigned long) &__rt_sig_stub) - 8;
211  # else /* sparc32 */
212  	if ((kact.sa_flags & SA_SIGINFO) != 0)
213  		stub = ((unsigned long) &__rt_sig_stub) - 8;
214  	else
215  		stub = ((unsigned long) &__sig_stub) - 8;
216  # endif
217  #endif
218  
219  
220  #ifdef __sparc__
221  	ret = TST_SYSCALL(__NR_rt_sigaction, signum,
222  			kact_p, koact_p,
223  			stub, sigsetsize);
224  #else
225  	ret = TST_SYSCALL(__NR_rt_sigaction, signum,
226  			kact_p, koact_p,
227  			sigsetsize);
228  #endif
229  
230  	if (ret >= 0) {
231  		if (oact && (oact != INVAL_SA_PTR)) {
232  			oact->sa_handler = koact.k_sa_handler;
233  			memcpy(&oact->sa_mask, &koact.sa_mask,
234  				sizeof(sigset_t));
235  			oact->sa_flags = koact.sa_flags;
236  #ifdef HAVE_SA_RESTORER
237  			oact->sa_restorer = koact.sa_restorer;
238  #endif
239  		}
240  	}
241  
242  	return ret;
243  }
244  
245  #endif /* LAPI_RT_SIGACTION_H__ */
246