linux32_signal.c revision 1.1.10.2 1 /* $NetBSD: linux32_signal.c,v 1.1.10.2 2006/04/22 11:38:14 simonb Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33 #include <sys/param.h>
34 #include <sys/ucred.h>
35 #include <sys/signalvar.h>
36 #include <sys/lwp.h>
37 #include <sys/time.h>
38
39 #include <compat/netbsd32/netbsd32.h>
40
41 #include <compat/linux32/common/linux32_types.h>
42 #include <compat/linux32/common/linux32_signal.h>
43 #include <compat/linux32/linux32_syscallargs.h>
44
45 #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s)))
46 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
47 & (1 << ((n) - 1) % LINUX32__NSIG_BPW))
48 #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
49 |= (1 << ((n) - 1) % LINUX32__NSIG_BPW))
50
51 extern const int native_to_linux32_signo[];
52 extern const int linux32_to_native_signo[];
53
54 void
55 linux32_to_native_sigset(bss, lss)
56 sigset_t *bss;
57 const linux32_sigset_t *lss;
58 {
59 int i, newsig;
60
61 sigemptyset(bss);
62 for (i = 1; i < LINUX32__NSIG; i++) {
63 if (linux32_sigismember(lss, i)) {
64 newsig = linux32_to_native_signo[i];
65 if (newsig)
66 sigaddset(bss, newsig);
67 }
68 }
69 }
70
71 void
72 native_to_linux32_sigset(lss, bss)
73 linux32_sigset_t *lss;
74 const sigset_t *bss;
75 {
76 int i, newsig;
77
78 linux32_sigemptyset(lss);
79 for (i = 1; i < NSIG; i++) {
80 if (sigismember(bss, i)) {
81 newsig = native_to_linux32_signo[i];
82 if (newsig)
83 linux32_sigaddset(lss, newsig);
84 }
85 }
86 }
87
88 unsigned int
89 native_to_linux32_sigflags(bsf)
90 const int bsf;
91 {
92 unsigned int lsf = 0;
93 if ((bsf & SA_NOCLDSTOP) != 0)
94 lsf |= LINUX32_SA_NOCLDSTOP;
95 if ((bsf & SA_NOCLDWAIT) != 0)
96 lsf |= LINUX32_SA_NOCLDWAIT;
97 if ((bsf & SA_ONSTACK) != 0)
98 lsf |= LINUX32_SA_ONSTACK;
99 if ((bsf & SA_RESTART) != 0)
100 lsf |= LINUX32_SA_RESTART;
101 if ((bsf & SA_NODEFER) != 0)
102 lsf |= LINUX32_SA_NOMASK;
103 if ((bsf & SA_RESETHAND) != 0)
104 lsf |= LINUX32_SA_ONESHOT;
105 if ((bsf & SA_SIGINFO) != 0)
106 lsf |= LINUX32_SA_SIGINFO;
107 return lsf;
108 }
109
110 int
111 linux32_to_native_sigflags(lsf)
112 const unsigned long lsf;
113 {
114 int bsf = 0;
115 if ((lsf & LINUX32_SA_NOCLDSTOP) != 0)
116 bsf |= SA_NOCLDSTOP;
117 if ((lsf & LINUX32_SA_NOCLDWAIT) != 0)
118 bsf |= SA_NOCLDWAIT;
119 if ((lsf & LINUX32_SA_ONSTACK) != 0)
120 bsf |= SA_ONSTACK;
121 if ((lsf & LINUX32_SA_RESTART) != 0)
122 bsf |= SA_RESTART;
123 if ((lsf & LINUX32_SA_ONESHOT) != 0)
124 bsf |= SA_RESETHAND;
125 if ((lsf & LINUX32_SA_NOMASK) != 0)
126 bsf |= SA_NODEFER;
127 if ((lsf & LINUX32_SA_SIGINFO) != 0)
128 bsf |= SA_SIGINFO;
129 if ((lsf & ~LINUX32_SA_ALLBITS) != 0) {
130 #ifdef DEBUG_LINUX
131 printf("linux32_old_to_native_sigflags: "
132 "%lx extra bits ignored\n", lsf);
133 #endif
134 }
135 return bsf;
136 }
137
138 void
139 linux32_to_native_sigaction(bsa, lsa)
140 struct sigaction *bsa;
141 const struct linux32_sigaction *lsa;
142 {
143 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler);
144 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
145 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags);
146 }
147
148 void
149 native_to_linux32_sigaction(lsa, bsa)
150 struct linux32_sigaction *lsa;
151 const struct sigaction *bsa;
152 {
153 lsa->linux_sa_handler = (linux32_handler_t)(long)bsa->sa_handler;
154 native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
155 lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags);
156 lsa->linux_sa_restorer = (linux32_restorer_t)NULL;
157 }
158
159 void
160 native_to_linux32_sigaltstack(lss, bss)
161 struct linux32_sigaltstack *lss;
162 const struct sigaltstack *bss;
163 {
164 lss->ss_sp = (netbsd32_voidp)(long)bss->ss_sp;
165 lss->ss_size = bss->ss_size;
166 if (bss->ss_flags & SS_ONSTACK)
167 lss->ss_flags = LINUX32_SS_ONSTACK;
168 else if (bss->ss_flags & SS_DISABLE)
169 lss->ss_flags = LINUX32_SS_DISABLE;
170 else
171 lss->ss_flags = 0;
172 }
173
174
175 void
176 native_to_linux32_old_sigset(lss, bss)
177 linux32_old_sigset_t *lss;
178 const sigset_t *bss;
179 {
180 linux32_sigset_t lsnew;
181
182 native_to_linux32_sigset(&lsnew, bss);
183
184 /* convert new sigset to old sigset */
185 *lss = lsnew.sig[0];
186 }
187
188 void
189 linux32_old_to_native_sigset(bss, lss)
190 sigset_t *bss;
191 const linux32_old_sigset_t *lss;
192 {
193 linux32_sigset_t ls;
194
195 bzero(&ls, sizeof(ls));
196 ls.sig[0] = *lss;
197
198 linux32_to_native_sigset(bss, &ls);
199 }
200
201 int
202 linux32_sys_rt_sigaction(l, v, retval)
203 struct lwp *l;
204 void *v;
205 register_t *retval;
206 {
207 struct linux32_sys_rt_sigaction_args /* {
208 syscallarg(int) signum;
209 syscallarg(const linux32_sigactionp_t) nsa;
210 syscallarg(linux32_sigactionp_t) osa;
211 syscallarg(netbsd32_size_t) sigsetsize;
212 } */ *uap = v;
213 struct linux32_sigaction nls32;
214 struct linux32_sigaction ols32;
215 struct sigaction ns;
216 struct sigaction os;
217 int error;
218 int sig;
219 int vers = 0;
220 void *tramp = NULL;
221
222 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
223 return EINVAL;
224
225 if (NETBSD32PTR64(SCARG(uap, nsa)) != NULL) {
226 if ((error = copyin(NETBSD32PTR64(SCARG(uap, nsa)),
227 &nls32, sizeof(nls32))) != 0)
228 return error;
229 linux32_to_native_sigaction(&ns, &nls32);
230 }
231
232 sig = SCARG(uap, signum);
233 if (sig < 0 || sig >= LINUX32__NSIG)
234 return EINVAL;
235 if (sig > 0 && !linux32_to_native_signo[sig]) {
236 /* unknown signal... */
237 os.sa_handler = SIG_IGN;
238 sigemptyset(&os.sa_mask);
239 os.sa_flags = 0;
240 } else {
241 if ((error = sigaction1(l->l_proc,
242 linux32_to_native_signo[sig],
243 NETBSD32PTR64(SCARG(uap, nsa)) ? &ns : NULL,
244 NETBSD32PTR64(SCARG(uap, osa)) ? &os : NULL,
245 tramp, vers)) != 0)
246 return error;
247 }
248
249 if (NETBSD32PTR64(SCARG(uap, osa)) != NULL) {
250 native_to_linux32_sigaction(&ols32, &os);
251
252 if ((error = copyout(&ols32, NETBSD32PTR64(SCARG(uap, osa)),
253 sizeof(ols32))) != 0)
254 return error;
255 }
256
257 return 0;
258 }
259
260 int
261 linux32_sys_rt_sigprocmask(l, v, retval)
262 struct lwp *l;
263 void *v;
264 register_t *retval;
265 {
266 struct linux32_sys_rt_sigprocmask_args /* {
267 syscallarg(int) how;
268 syscallarg(const linux32_sigsetp_t) set;
269 syscallarg(linux32_sigsetp_t) oset;
270 syscallarg(netbsd32_size_t) sigsetsize;
271 } */ *uap = v;
272 struct proc *p = l->l_proc;
273 linux32_sigset_t nls32, ols32;
274 sigset_t ns, os;
275 int error;
276 int how;
277
278 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
279 return EINVAL;
280
281 switch (SCARG(uap, how)) {
282 case LINUX32_SIG_BLOCK:
283 how = SIG_BLOCK;
284 break;
285 case LINUX32_SIG_UNBLOCK:
286 how = SIG_UNBLOCK;
287 break;
288 case LINUX32_SIG_SETMASK:
289 how = SIG_SETMASK;
290 break;
291 default:
292 return EINVAL;
293 break;
294 }
295
296 if (NETBSD32PTR64(SCARG(uap, set)) != NULL) {
297 if ((error = copyin(NETBSD32PTR64(SCARG(uap, set)),
298 &nls32, sizeof(nls32))) != 0)
299 return error;
300 linux32_to_native_sigset(&ns, &nls32);
301 }
302
303 if ((error = sigprocmask1(p, how,
304 NETBSD32PTR64(SCARG(uap, set)) ? &ns : NULL,
305 NETBSD32PTR64(SCARG(uap, oset)) ? &os : NULL)) != 0)
306 return error;
307
308 if (NETBSD32PTR64(SCARG(uap, oset)) != NULL) {
309 native_to_linux32_sigset(&ols32, &os);
310 if ((error = copyout(&ols32,
311 NETBSD32PTR64(SCARG(uap, oset)), sizeof(ols32))) != 0)
312 return error;
313 }
314
315 return 0;
316 }
317
318 int
319 linux32_sys_kill(l, v, retval)
320 struct lwp *l;
321 void *v;
322 register_t *retval;
323 {
324 struct linux32_sys_kill_args /* {
325 syscallarg(int) pid;
326 syscallarg(int) signum;
327 } */ *uap = v;
328
329 struct sys_kill_args ka;
330 int sig;
331
332 SCARG(&ka, pid) = SCARG(uap, pid);
333 sig = SCARG(uap, signum);
334 if (sig < 0 || sig >= LINUX32__NSIG)
335 return (EINVAL);
336 SCARG(&ka, signum) = linux32_to_native_signo[sig];
337 return sys_kill(l, &ka, retval);
338 }
339
340 int
341 linux32_sys_rt_sigsuspend(l, v, retval)
342 struct lwp *l;
343 void *v;
344 register_t *retval;
345 {
346 struct linux32_sys_rt_sigsuspend_args /* {
347 syscallarg(linux32_sigsetp_t) unewset;
348 syscallarg(netbsd32_size_t) sigsetsize;
349 } */ *uap = v;
350 linux32_sigset_t lss;
351 sigset_t bss;
352 int error;
353
354 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
355 return EINVAL;
356
357 if ((error = copyin(NETBSD32PTR64(SCARG(uap, unewset)),
358 &lss, sizeof(linux32_sigset_t))) != 0)
359 return error;
360
361 linux32_to_native_sigset(&bss, &lss);
362
363 return sigsuspend1(l->l_proc, &bss);
364 }
365
366 int
367 linux32_sys_signal(l, v, retval)
368 struct lwp *l;
369 void *v;
370 register_t *retval;
371 {
372 struct linux32_sys_signal_args /* {
373 syscallarg(int) signum;
374 syscallarg(linux32_handler_t) handler;
375 } */ *uap = v;
376 struct proc *p = l->l_proc;
377 struct sigaction nbsa, obsa;
378 int error, sig;
379
380 *retval = -1;
381
382 sig = SCARG(uap, signum);
383 if (sig < 0 || sig >= LINUX32__NSIG)
384 return EINVAL;
385
386 nbsa.sa_handler = NETBSD32PTR64(SCARG(uap, handler));
387 sigemptyset(&nbsa.sa_mask);
388 nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
389
390 if ((error = sigaction1(p, linux32_to_native_signo[sig],
391 &nbsa, &obsa, NULL, 0)) != 0)
392 return error;
393
394 *retval = (int)(long)obsa.sa_handler;
395 return 0;
396 }
397