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