linux32_signal.c revision 1.3 1 /* $NetBSD: linux32_signal.c,v 1.3 2007/03/16 22:21:40 dsl 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 #include <sys/proc.h>
39
40 #include <compat/netbsd32/netbsd32.h>
41
42 #include <compat/linux32/common/linux32_types.h>
43 #include <compat/linux32/common/linux32_signal.h>
44 #include <compat/linux32/linux32_syscallargs.h>
45
46 #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s)))
47 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
48 & (1 << ((n) - 1) % LINUX32__NSIG_BPW))
49 #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
50 |= (1 << ((n) - 1) % LINUX32__NSIG_BPW))
51
52 extern const int native_to_linux32_signo[];
53 extern const int linux32_to_native_signo[];
54
55 void
56 linux32_to_native_sigset(bss, lss)
57 sigset_t *bss;
58 const linux32_sigset_t *lss;
59 {
60 int i, newsig;
61
62 sigemptyset(bss);
63 for (i = 1; i < LINUX32__NSIG; i++) {
64 if (linux32_sigismember(lss, i)) {
65 newsig = linux32_to_native_signo[i];
66 if (newsig)
67 sigaddset(bss, newsig);
68 }
69 }
70 }
71
72 void
73 native_to_linux32_sigset(lss, bss)
74 linux32_sigset_t *lss;
75 const sigset_t *bss;
76 {
77 int i, newsig;
78
79 linux32_sigemptyset(lss);
80 for (i = 1; i < NSIG; i++) {
81 if (sigismember(bss, i)) {
82 newsig = native_to_linux32_signo[i];
83 if (newsig)
84 linux32_sigaddset(lss, newsig);
85 }
86 }
87 }
88
89 unsigned int
90 native_to_linux32_sigflags(bsf)
91 const int bsf;
92 {
93 unsigned int lsf = 0;
94 if ((bsf & SA_NOCLDSTOP) != 0)
95 lsf |= LINUX32_SA_NOCLDSTOP;
96 if ((bsf & SA_NOCLDWAIT) != 0)
97 lsf |= LINUX32_SA_NOCLDWAIT;
98 if ((bsf & SA_ONSTACK) != 0)
99 lsf |= LINUX32_SA_ONSTACK;
100 if ((bsf & SA_RESTART) != 0)
101 lsf |= LINUX32_SA_RESTART;
102 if ((bsf & SA_NODEFER) != 0)
103 lsf |= LINUX32_SA_NOMASK;
104 if ((bsf & SA_RESETHAND) != 0)
105 lsf |= LINUX32_SA_ONESHOT;
106 if ((bsf & SA_SIGINFO) != 0)
107 lsf |= LINUX32_SA_SIGINFO;
108 return lsf;
109 }
110
111 int
112 linux32_to_native_sigflags(lsf)
113 const unsigned long lsf;
114 {
115 int bsf = 0;
116 if ((lsf & LINUX32_SA_NOCLDSTOP) != 0)
117 bsf |= SA_NOCLDSTOP;
118 if ((lsf & LINUX32_SA_NOCLDWAIT) != 0)
119 bsf |= SA_NOCLDWAIT;
120 if ((lsf & LINUX32_SA_ONSTACK) != 0)
121 bsf |= SA_ONSTACK;
122 if ((lsf & LINUX32_SA_RESTART) != 0)
123 bsf |= SA_RESTART;
124 if ((lsf & LINUX32_SA_ONESHOT) != 0)
125 bsf |= SA_RESETHAND;
126 if ((lsf & LINUX32_SA_NOMASK) != 0)
127 bsf |= SA_NODEFER;
128 if ((lsf & LINUX32_SA_SIGINFO) != 0)
129 bsf |= SA_SIGINFO;
130 if ((lsf & ~LINUX32_SA_ALLBITS) != 0) {
131 #ifdef DEBUG_LINUX
132 printf("linux32_old_to_native_sigflags: "
133 "%lx extra bits ignored\n", lsf);
134 #endif
135 }
136 return bsf;
137 }
138
139 void
140 linux32_to_native_sigaction(bsa, lsa)
141 struct sigaction *bsa;
142 const struct linux32_sigaction *lsa;
143 {
144 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler);
145 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
146 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags);
147 }
148
149 void
150 native_to_linux32_sigaction(lsa, bsa)
151 struct linux32_sigaction *lsa;
152 const struct sigaction *bsa;
153 {
154 NETBSD32PTR32(lsa->linux_sa_handler, bsa->sa_handler);
155 native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
156 lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags);
157 NETBSD32PTR32(lsa->linux_sa_restorer, NULL);
158 }
159
160 void
161 native_to_linux32_sigaltstack(lss, bss)
162 struct linux32_sigaltstack *lss;
163 const struct sigaltstack *bss;
164 {
165 NETBSD32PTR32(lss->ss_sp, bss->ss_sp);
166 lss->ss_size = bss->ss_size;
167 if (bss->ss_flags & SS_ONSTACK)
168 lss->ss_flags = LINUX32_SS_ONSTACK;
169 else if (bss->ss_flags & SS_DISABLE)
170 lss->ss_flags = LINUX32_SS_DISABLE;
171 else
172 lss->ss_flags = 0;
173 }
174
175
176 void
177 native_to_linux32_old_sigset(lss, bss)
178 linux32_old_sigset_t *lss;
179 const sigset_t *bss;
180 {
181 linux32_sigset_t lsnew;
182
183 native_to_linux32_sigset(&lsnew, bss);
184
185 /* convert new sigset to old sigset */
186 *lss = lsnew.sig[0];
187 }
188
189 void
190 linux32_old_to_native_sigset(bss, lss)
191 sigset_t *bss;
192 const linux32_old_sigset_t *lss;
193 {
194 linux32_sigset_t ls;
195
196 bzero(&ls, sizeof(ls));
197 ls.sig[0] = *lss;
198
199 linux32_to_native_sigset(bss, &ls);
200 }
201
202 int
203 linux32_sys_rt_sigaction(l, v, retval)
204 struct lwp *l;
205 void *v;
206 register_t *retval;
207 {
208 struct linux32_sys_rt_sigaction_args /* {
209 syscallarg(int) signum;
210 syscallarg(const linux32_sigactionp_t) nsa;
211 syscallarg(linux32_sigactionp_t) osa;
212 syscallarg(netbsd32_size_t) sigsetsize;
213 } */ *uap = v;
214 struct linux32_sigaction nls32;
215 struct linux32_sigaction ols32;
216 struct sigaction ns;
217 struct sigaction os;
218 int error;
219 int sig;
220 int vers = 0;
221 void *tramp = NULL;
222
223 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
224 return EINVAL;
225
226 if (NETBSD32PTR64(SCARG(uap, nsa)) != NULL) {
227 if ((error = copyin(NETBSD32PTR64(SCARG(uap, nsa)),
228 &nls32, sizeof(nls32))) != 0)
229 return error;
230 linux32_to_native_sigaction(&ns, &nls32);
231 }
232
233 sig = SCARG(uap, signum);
234 if (sig < 0 || sig >= LINUX32__NSIG)
235 return EINVAL;
236 if (sig > 0 && !linux32_to_native_signo[sig]) {
237 /* unknown signal... */
238 os.sa_handler = SIG_IGN;
239 sigemptyset(&os.sa_mask);
240 os.sa_flags = 0;
241 } else {
242 if ((error = sigaction1(l,
243 linux32_to_native_signo[sig],
244 NETBSD32PTR64(SCARG(uap, nsa)) ? &ns : NULL,
245 NETBSD32PTR64(SCARG(uap, osa)) ? &os : NULL,
246 tramp, vers)) != 0)
247 return error;
248 }
249
250 if (NETBSD32PTR64(SCARG(uap, osa)) != NULL) {
251 native_to_linux32_sigaction(&ols32, &os);
252
253 if ((error = copyout(&ols32, NETBSD32PTR64(SCARG(uap, osa)),
254 sizeof(ols32))) != 0)
255 return error;
256 }
257
258 return 0;
259 }
260
261 int
262 linux32_sys_rt_sigprocmask(l, v, retval)
263 struct lwp *l;
264 void *v;
265 register_t *retval;
266 {
267 struct linux32_sys_rt_sigprocmask_args /* {
268 syscallarg(int) how;
269 syscallarg(const linux32_sigsetp_t) set;
270 syscallarg(linux32_sigsetp_t) oset;
271 syscallarg(netbsd32_size_t) sigsetsize;
272 } */ *uap = v;
273 struct proc *p = l->l_proc;
274 linux32_sigset_t nls32, ols32;
275 sigset_t ns, os;
276 int error;
277 int how;
278
279 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
280 return EINVAL;
281
282 switch (SCARG(uap, how)) {
283 case LINUX32_SIG_BLOCK:
284 how = SIG_BLOCK;
285 break;
286 case LINUX32_SIG_UNBLOCK:
287 how = SIG_UNBLOCK;
288 break;
289 case LINUX32_SIG_SETMASK:
290 how = SIG_SETMASK;
291 break;
292 default:
293 return EINVAL;
294 break;
295 }
296
297 if (NETBSD32PTR64(SCARG(uap, set)) != NULL) {
298 if ((error = copyin(NETBSD32PTR64(SCARG(uap, set)),
299 &nls32, sizeof(nls32))) != 0)
300 return error;
301 linux32_to_native_sigset(&ns, &nls32);
302 }
303
304 mutex_enter(&p->p_smutex);
305 error = sigprocmask1(l, how,
306 NETBSD32PTR64(SCARG(uap, set)) ? &ns : NULL,
307 NETBSD32PTR64(SCARG(uap, oset)) ? &os : NULL);
308 mutex_exit(&p->p_smutex);
309
310 if (error != 0)
311 return error;
312
313 if (NETBSD32PTR64(SCARG(uap, oset)) != NULL) {
314 native_to_linux32_sigset(&ols32, &os);
315 if ((error = copyout(&ols32,
316 NETBSD32PTR64(SCARG(uap, oset)), sizeof(ols32))) != 0)
317 return error;
318 }
319
320 return 0;
321 }
322
323 int
324 linux32_sys_kill(l, v, retval)
325 struct lwp *l;
326 void *v;
327 register_t *retval;
328 {
329 struct linux32_sys_kill_args /* {
330 syscallarg(int) pid;
331 syscallarg(int) signum;
332 } */ *uap = v;
333
334 struct sys_kill_args ka;
335 int sig;
336
337 SCARG(&ka, pid) = SCARG(uap, pid);
338 sig = SCARG(uap, signum);
339 if (sig < 0 || sig >= LINUX32__NSIG)
340 return (EINVAL);
341 SCARG(&ka, signum) = linux32_to_native_signo[sig];
342 return sys_kill(l, &ka, retval);
343 }
344
345 int
346 linux32_sys_rt_sigsuspend(l, v, retval)
347 struct lwp *l;
348 void *v;
349 register_t *retval;
350 {
351 struct linux32_sys_rt_sigsuspend_args /* {
352 syscallarg(linux32_sigsetp_t) unewset;
353 syscallarg(netbsd32_size_t) sigsetsize;
354 } */ *uap = v;
355 linux32_sigset_t lss;
356 sigset_t bss;
357 int error;
358
359 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
360 return EINVAL;
361
362 if ((error = copyin(NETBSD32PTR64(SCARG(uap, unewset)),
363 &lss, sizeof(linux32_sigset_t))) != 0)
364 return error;
365
366 linux32_to_native_sigset(&bss, &lss);
367
368 return sigsuspend1(l, &bss);
369 }
370
371 int
372 linux32_sys_signal(l, v, retval)
373 struct lwp *l;
374 void *v;
375 register_t *retval;
376 {
377 struct linux32_sys_signal_args /* {
378 syscallarg(int) signum;
379 syscallarg(linux32_handler_t) handler;
380 } */ *uap = v;
381 struct sigaction nbsa, obsa;
382 int error, sig;
383
384 *retval = -1;
385
386 sig = SCARG(uap, signum);
387 if (sig < 0 || sig >= LINUX32__NSIG)
388 return EINVAL;
389
390 nbsa.sa_handler = NETBSD32PTR64(SCARG(uap, handler));
391 sigemptyset(&nbsa.sa_mask);
392 nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
393
394 if ((error = sigaction1(l, linux32_to_native_signo[sig],
395 &nbsa, &obsa, NULL, 0)) != 0)
396 return error;
397
398 *retval = (int)(long)obsa.sa_handler;
399 return 0;
400 }
401