netbsd32_signal.c revision 1.21.4.1 1 /* $NetBSD: netbsd32_signal.c,v 1.21.4.1 2007/07/11 20:04:32 mjf Exp $ */
2
3 /*
4 * Copyright (c) 1998, 2001 Matthew R. Green
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.21.4.1 2007/07/11 20:04:32 mjf Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/mount.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include <sys/signalvar.h>
41 #include <sys/proc.h>
42 #include <sys/wait.h>
43 #include <sys/dirent.h>
44
45 #include <uvm/uvm_extern.h>
46
47 #include <compat/netbsd32/netbsd32.h>
48 #include <compat/netbsd32/netbsd32_conv.h>
49 #include <compat/netbsd32/netbsd32_syscallargs.h>
50
51 #include <compat/sys/signal.h>
52 #include <compat/sys/signalvar.h>
53 #include <compat/sys/siginfo.h>
54 #include <compat/sys/ucontext.h>
55 #include <compat/common/compat_sigaltstack.h>
56
57 #ifdef unused
58 static void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *);
59 #endif
60
61
62 int
63 netbsd32_sigaction(l, v, retval)
64 struct lwp *l;
65 void *v;
66 register_t *retval;
67 {
68 struct netbsd32_sigaction_args /* {
69 syscallarg(int) signum;
70 syscallarg(const netbsd32_sigactionp_t) nsa;
71 syscallarg(netbsd32_sigactionp_t) osa;
72 } */ *uap = v;
73 struct sigaction nsa, osa;
74 struct netbsd32_sigaction *sa32p, sa32;
75 int error;
76
77 if (SCARG_P32(uap, nsa)) {
78 sa32p = SCARG_P32(uap, nsa);
79 if (copyin(sa32p, &sa32, sizeof(sa32)))
80 return EFAULT;
81 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler);
82 nsa.sa_mask = sa32.netbsd32_sa_mask;
83 nsa.sa_flags = sa32.netbsd32_sa_flags;
84 }
85 error = sigaction1(l, SCARG(uap, signum),
86 SCARG_P32(uap, nsa) ? &nsa : 0,
87 SCARG_P32(uap, osa) ? &osa : 0,
88 NULL, 0);
89
90 if (error)
91 return (error);
92
93 if (SCARG_P32(uap, osa)) {
94 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler);
95 sa32.netbsd32_sa_mask = osa.sa_mask;
96 sa32.netbsd32_sa_flags = osa.sa_flags;
97 sa32p = SCARG_P32(uap, osa);
98 if (copyout(&sa32, sa32p, sizeof(sa32)))
99 return EFAULT;
100 }
101
102 return (0);
103 }
104
105 int
106 netbsd32___sigaltstack14(l, v, retval)
107 struct lwp *l;
108 void *v;
109 register_t *retval;
110 {
111 struct netbsd32___sigaltstack14_args /* {
112 syscallarg(const netbsd32_sigaltstackp_t) nss;
113 syscallarg(netbsd32_sigaltstackp_t) oss;
114 } */ *uap = v;
115 compat_sigaltstack(uap, netbsd32_sigaltstack, SS_ONSTACK, SS_DISABLE);
116 }
117
118 /* ARGSUSED */
119 int
120 netbsd32___sigaction14(l, v, retval)
121 struct lwp *l;
122 void *v;
123 register_t *retval;
124 {
125 struct netbsd32___sigaction14_args /* {
126 syscallarg(int) signum;
127 syscallarg(const struct sigaction *) nsa;
128 syscallarg(struct sigaction *) osa;
129 } */ *uap = v;
130 struct netbsd32_sigaction sa32;
131 struct sigaction nsa, osa;
132 int error;
133
134 if (SCARG_P32(uap, nsa)) {
135 error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32));
136 if (error)
137 return (error);
138 nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler);
139 nsa.sa_mask = sa32.netbsd32_sa_mask;
140 nsa.sa_flags = sa32.netbsd32_sa_flags;
141 }
142 error = sigaction1(l, SCARG(uap, signum),
143 SCARG_P32(uap, nsa) ? &nsa : 0,
144 SCARG_P32(uap, osa) ? &osa : 0,
145 NULL, 0);
146 if (error)
147 return (error);
148 if (SCARG_P32(uap, osa)) {
149 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler);
150 sa32.netbsd32_sa_mask = osa.sa_mask;
151 sa32.netbsd32_sa_flags = osa.sa_flags;
152 error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32));
153 if (error)
154 return (error);
155 }
156 return (0);
157 }
158
159 /* ARGSUSED */
160 int
161 netbsd32___sigaction_sigtramp(l, v, retval)
162 struct lwp *l;
163 void *v;
164 register_t *retval;
165 {
166 struct netbsd32___sigaction_sigtramp_args /* {
167 syscallarg(int) signum;
168 syscallarg(const netbsd32_sigactionp_t) nsa;
169 syscallarg(netbsd32_sigactionp_t) osa;
170 syscallarg(netbsd32_voidp) tramp;
171 syscallarg(int) vers;
172 } */ *uap = v;
173 struct netbsd32_sigaction sa32;
174 struct sigaction nsa, osa;
175 int error;
176
177 if (SCARG_P32(uap, nsa)) {
178 error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32));
179 if (error)
180 return (error);
181 nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler);
182 nsa.sa_mask = sa32.netbsd32_sa_mask;
183 nsa.sa_flags = sa32.netbsd32_sa_flags;
184 }
185 error = sigaction1(l, SCARG(uap, signum),
186 SCARG_P32(uap, nsa) ? &nsa : 0,
187 SCARG_P32(uap, osa) ? &osa : 0,
188 SCARG_P32(uap, tramp), SCARG(uap, vers));
189 if (error)
190 return (error);
191 if (SCARG_P32(uap, osa)) {
192 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler);
193 sa32.netbsd32_sa_mask = osa.sa_mask;
194 sa32.netbsd32_sa_flags = osa.sa_flags;
195 error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32));
196 if (error)
197 return (error);
198 }
199 return (0);
200 }
201
202 #ifdef unused
203 static void
204 netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32)
205 {
206 memset(si, 0, sizeof (*si));
207 si->si_signo = si32->si_signo;
208 si->si_code = si32->si_code;
209 si->si_errno = si32->si_errno;
210
211 switch (si32->si_signo) {
212 case SIGILL:
213 case SIGBUS:
214 case SIGSEGV:
215 case SIGFPE:
216 case SIGTRAP:
217 si->si_addr = NETBSD32PTR64(si32->si_addr);
218 si->si_trap = si32->si_trap;
219 break;
220 case SIGALRM:
221 case SIGVTALRM:
222 case SIGPROF:
223 si->si_pid = si32->si_pid;
224 si->si_uid = si32->si_uid;
225 /*
226 * XXX sival_ptr is currently unused.
227 */
228 si->si_value.sival_int = si32->si_value.sival_int;
229 break;
230 case SIGCHLD:
231 si->si_pid = si32->si_pid;
232 si->si_uid = si32->si_uid;
233 si->si_utime = si32->si_utime;
234 si->si_stime = si32->si_stime;
235 break;
236 case SIGURG:
237 case SIGIO:
238 si->si_band = si32->si_band;
239 si->si_fd = si32->si_fd;
240 break;
241 }
242 }
243 #endif
244
245 void
246 netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si)
247 {
248 memset(si32, 0, sizeof (*si32));
249 si32->si_signo = si->si_signo;
250 si32->si_code = si->si_code;
251 si32->si_errno = si->si_errno;
252
253 switch (si32->si_signo) {
254 case 0: /* SA */
255 si32->si_value.sival_int = si->si_value.sival_int;
256 break;
257 case SIGILL:
258 case SIGBUS:
259 case SIGSEGV:
260 case SIGFPE:
261 case SIGTRAP:
262 si32->si_addr = (uint32_t)(uintptr_t)si->si_addr;
263 si32->si_trap = si->si_trap;
264 break;
265 case SIGALRM:
266 case SIGVTALRM:
267 case SIGPROF:
268 si32->si_pid = si->si_pid;
269 si32->si_uid = si->si_uid;
270 /*
271 * XXX sival_ptr is currently unused.
272 */
273 si32->si_value.sival_int = si->si_value.sival_int;
274 break;
275 case SIGCHLD:
276 si32->si_pid = si->si_pid;
277 si32->si_uid = si->si_uid;
278 si32->si_status = si->si_status;
279 si32->si_utime = si->si_utime;
280 si32->si_stime = si->si_stime;
281 break;
282 case SIGURG:
283 case SIGIO:
284 si32->si_band = si->si_band;
285 si32->si_fd = si->si_fd;
286 break;
287 }
288 }
289
290 void
291 getucontext32(struct lwp *l, ucontext32_t *ucp)
292 {
293 struct proc *p = l->l_proc;
294
295 LOCK_ASSERT(mutex_owned(&p->p_smutex));
296
297 ucp->uc_flags = 0;
298 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink;
299
300 ucp->uc_sigmask = l->l_sigmask;
301 ucp->uc_flags |= _UC_SIGMASK;
302
303 /*
304 * The (unsupplied) definition of the `current execution stack'
305 * in the System V Interface Definition appears to allow returning
306 * the main context stack.
307 */
308 if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) {
309 ucp->uc_stack.ss_sp = USRSTACK32;
310 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize);
311 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */
312 } else {
313 /* Simply copy alternate signal execution stack. */
314 ucp->uc_stack.ss_sp =
315 (uint32_t)(intptr_t)l->l_sigstk.ss_sp;
316 ucp->uc_stack.ss_size = l->l_sigstk.ss_size;
317 ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags;
318 }
319 ucp->uc_flags |= _UC_STACK;
320 mutex_exit(&p->p_smutex);
321 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags);
322 mutex_enter(&p->p_smutex);
323 }
324
325 /* ARGSUSED */
326 int
327 netbsd32_getcontext(struct lwp *l, void *v, register_t *retval)
328 {
329 struct netbsd32_getcontext_args /* {
330 syscallarg(netbsd32_ucontextp) ucp;
331 } */ *uap = v;
332 struct proc *p = l->l_proc;
333 ucontext32_t uc;
334
335 mutex_enter(&p->p_smutex);
336 getucontext32(l, &uc);
337 mutex_exit(&p->p_smutex);
338
339 return copyout(&uc, SCARG_P32(uap, ucp), sizeof (ucontext32_t));
340 }
341
342 int
343 setucontext32(struct lwp *l, const ucontext32_t *ucp)
344 {
345 struct proc *p = l->l_proc;
346 int error;
347
348 LOCK_ASSERT(mutex_owned(&p->p_smutex));
349
350 if ((ucp->uc_flags & _UC_SIGMASK) != 0) {
351 error = sigprocmask1(l, SIG_SETMASK, &ucp->uc_sigmask, NULL);
352 if (error != 0)
353 return error;
354 }
355
356 mutex_exit(&p->p_smutex);
357 error = cpu_setmcontext32(l, &ucp->uc_mcontext, ucp->uc_flags);
358 mutex_enter(&p->p_smutex);
359 if (error != 0)
360 return (error);
361
362 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link;
363
364 /*
365 * If there was stack information, update whether or not we are
366 * still running on an alternate signal stack.
367 */
368 if ((ucp->uc_flags & _UC_STACK) != 0) {
369 if (ucp->uc_stack.ss_flags & SS_ONSTACK)
370 l->l_sigstk.ss_flags |= SS_ONSTACK;
371 else
372 l->l_sigstk.ss_flags &= ~SS_ONSTACK;
373 }
374
375 return 0;
376 }
377
378 /* ARGSUSED */
379 int
380 netbsd32_setcontext(struct lwp *l, void *v, register_t *retval)
381 {
382 struct netbsd32_setcontext_args /* {
383 syscallarg(netbsd32_ucontextp) ucp;
384 } */ *uap = v;
385 ucontext32_t uc;
386 int error;
387 struct proc *p = l->l_proc;
388
389 error = copyin(SCARG_P32(uap, ucp), &uc, sizeof (uc));
390 if (error)
391 return (error);
392 if (!(uc.uc_flags & _UC_CPU))
393 return (EINVAL);
394 mutex_enter(&p->p_smutex);
395 error = setucontext32(l, &uc);
396 mutex_exit(&p->p_smutex);
397 if (error)
398 return (error);
399
400 return (EJUSTRETURN);
401 }
402
403 static int
404 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size)
405 {
406 const siginfo_t *info = src;
407 siginfo32_t info32;
408
409 netbsd32_si_to_si32(&info32, info);
410
411 return copyout(&info32, dst, sizeof(info32));
412 }
413
414 static int
415 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size)
416 {
417 struct timespec *ts = dst;
418 struct netbsd32_timespec ts32;
419 int error;
420
421 error = copyin(src, &ts32, sizeof(ts32));
422 if (error)
423 return error;
424
425 netbsd32_to_timespec(&ts32, ts);
426 return 0;
427 }
428
429 static int
430 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size)
431 {
432 const struct timespec *ts = src;
433 struct netbsd32_timespec ts32;
434
435 netbsd32_from_timespec(ts, &ts32);
436
437 return copyout(&ts32, dst, sizeof(ts32));
438 }
439
440 int
441 netbsd32___sigtimedwait(struct lwp *l, void *v, register_t *retval)
442 {
443 struct netbsd32___sigtimedwait_args /* {
444 syscallarg(netbsd32_sigsetp_t) set;
445 syscallarg(netbsd32_siginfop_t) info;
446 syscallarg(netbsd32_timespecp_t) timeout;
447 } */ *uap = v;
448 struct sys___sigtimedwait_args ua;
449
450 NETBSD32TOP_UAP(set, const sigset_t);
451 NETBSD32TOP_UAP(info, siginfo_t);
452 NETBSD32TOP_UAP(timeout, struct timespec);
453
454 return __sigtimedwait1(l, &ua, retval, netbsd32_sigtimedwait_put_info,
455 netbsd32_sigtimedwait_fetch_timeout,
456 netbsd32_sigtimedwait_put_timeout);
457 }
458