netbsd32_signal.c revision 1.12 1 /* $NetBSD: netbsd32_signal.c,v 1.12 2005/09/13 03:23:09 christos 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.12 2005/09/13 03:23:09 christos 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/ucontext.h>
54
55 int
56 netbsd32_sigaction(l, v, retval)
57 struct lwp *l;
58 void *v;
59 register_t *retval;
60 {
61 struct netbsd32_sigaction_args /* {
62 syscallarg(int) signum;
63 syscallarg(const netbsd32_sigactionp_t) nsa;
64 syscallarg(netbsd32_sigactionp_t) osa;
65 } */ *uap = v;
66 struct sigaction nsa, osa;
67 struct netbsd32_sigaction *sa32p, sa32;
68 int error;
69
70 if (SCARG(uap, nsa)) {
71 sa32p =
72 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, nsa));
73 if (copyin(sa32p, &sa32, sizeof(sa32)))
74 return EFAULT;
75 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler);
76 nsa.sa_mask = sa32.netbsd32_sa_mask;
77 nsa.sa_flags = sa32.netbsd32_sa_flags;
78 }
79 error = sigaction1(l->l_proc, SCARG(uap, signum),
80 SCARG(uap, nsa) ? &nsa : 0,
81 SCARG(uap, osa) ? &osa : 0,
82 NULL, 0);
83
84 if (error)
85 return (error);
86
87 if (SCARG(uap, osa)) {
88 sa32.netbsd32_sa_handler = (netbsd32_sigactionp_t)(u_long)osa.sa_handler;
89 sa32.netbsd32_sa_mask = osa.sa_mask;
90 sa32.netbsd32_sa_flags = osa.sa_flags;
91 sa32p =
92 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, osa));
93 if (copyout(&sa32, sa32p, sizeof(sa32)))
94 return EFAULT;
95 }
96
97 return (0);
98 }
99
100 int
101 netbsd32___sigaltstack14(l, v, retval)
102 struct lwp *l;
103 void *v;
104 register_t *retval;
105 {
106 struct netbsd32___sigaltstack14_args /* {
107 syscallarg(const netbsd32_sigaltstackp_t) nss;
108 syscallarg(netbsd32_sigaltstackp_t) oss;
109 } */ *uap = v;
110 struct netbsd32_sigaltstack s32;
111 struct sigaltstack nss, oss;
112 int error;
113
114 if (SCARG(uap, nss)) {
115 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nss)), &s32,
116 sizeof(s32));
117 if (error)
118 return (error);
119 nss.ss_sp = (void *)NETBSD32PTR64(s32.ss_sp);
120 nss.ss_size = (size_t)s32.ss_size;
121 nss.ss_flags = s32.ss_flags;
122 }
123 error = sigaltstack1(l->l_proc,
124 SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0);
125 if (error)
126 return (error);
127 if (SCARG(uap, oss)) {
128 s32.ss_sp = (netbsd32_voidp)(u_long)oss.ss_sp;
129 s32.ss_size = (netbsd32_size_t)oss.ss_size;
130 s32.ss_flags = oss.ss_flags;
131 error = copyout(&s32, (caddr_t)NETBSD32PTR64(SCARG(uap, oss)),
132 sizeof(s32));
133 if (error)
134 return (error);
135 }
136 return (0);
137 }
138
139 /* ARGSUSED */
140 int
141 netbsd32___sigaction14(l, v, retval)
142 struct lwp *l;
143 void *v;
144 register_t *retval;
145 {
146 struct netbsd32___sigaction14_args /* {
147 syscallarg(int) signum;
148 syscallarg(const struct sigaction *) nsa;
149 syscallarg(struct sigaction *) osa;
150 } */ *uap = v;
151 struct netbsd32_sigaction sa32;
152 struct sigaction nsa, osa;
153 int error;
154
155 if (SCARG(uap, nsa)) {
156 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32,
157 sizeof(sa32));
158 if (error)
159 return (error);
160 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler);
161 nsa.sa_mask = sa32.netbsd32_sa_mask;
162 nsa.sa_flags = sa32.netbsd32_sa_flags;
163 }
164 error = sigaction1(l->l_proc, SCARG(uap, signum),
165 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
166 NULL, 0);
167 if (error)
168 return (error);
169 if (SCARG(uap, osa)) {
170 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler;
171 sa32.netbsd32_sa_mask = osa.sa_mask;
172 sa32.netbsd32_sa_flags = osa.sa_flags;
173 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)),
174 sizeof(sa32));
175 if (error)
176 return (error);
177 }
178 return (0);
179 }
180
181 /* ARGSUSED */
182 int
183 netbsd32___sigaction_sigtramp(l, v, retval)
184 struct lwp *l;
185 void *v;
186 register_t *retval;
187 {
188 struct netbsd32___sigaction_sigtramp_args /* {
189 syscallarg(int) signum;
190 syscallarg(const netbsd32_sigactionp_t) nsa;
191 syscallarg(netbsd32_sigactionp_t) osa;
192 syscallarg(netbsd32_voidp) tramp;
193 syscallarg(int) vers;
194 } */ *uap = v;
195 struct proc *p = l->l_proc;
196 struct netbsd32_sigaction sa32;
197 struct sigaction nsa, osa;
198 int error;
199
200 if (SCARG(uap, nsa)) {
201 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32,
202 sizeof(sa32));
203 if (error)
204 return (error);
205 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler);
206 nsa.sa_mask = sa32.netbsd32_sa_mask;
207 nsa.sa_flags = sa32.netbsd32_sa_flags;
208 }
209 error = sigaction1(p, SCARG(uap, signum),
210 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
211 NETBSD32PTR64(SCARG(uap, tramp)), SCARG(uap, vers));
212 if (error)
213 return (error);
214 if (SCARG(uap, osa)) {
215 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler;
216 sa32.netbsd32_sa_mask = osa.sa_mask;
217 sa32.netbsd32_sa_flags = osa.sa_flags;
218 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)),
219 sizeof(sa32));
220 if (error)
221 return (error);
222 }
223 return (0);
224 }
225
226 void
227 netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32)
228 {
229 memset(si, 0, sizeof (*si));
230 si->si_signo = si32->si_signo;
231 si->si_code = si32->si_code;
232 si->si_errno = si32->si_errno;
233
234 switch (si32->si_signo) {
235 case SIGILL:
236 case SIGBUS:
237 case SIGSEGV:
238 case SIGFPE:
239 case SIGTRAP:
240 si->si_addr = (void *)NETBSD32PTR64(si32->si_addr);
241 si->si_trap = si32->si_trap;
242 break;
243 case SIGALRM:
244 case SIGVTALRM:
245 case SIGPROF:
246 si->si_pid = si32->si_pid;
247 si->si_uid = si32->si_uid;
248 /*
249 * XXX sival_ptr is currently unused.
250 */
251 si->si_sigval.sival_int = si32->si_sigval.sival_int;
252 break;
253 case SIGCHLD:
254 si->si_pid = si32->si_pid;
255 si->si_uid = si32->si_uid;
256 si->si_utime = si32->si_utime;
257 si->si_stime = si32->si_stime;
258 break;
259 case SIGURG:
260 case SIGIO:
261 si->si_band = si32->si_band;
262 si->si_fd = si32->si_fd;
263 break;
264 }
265 }
266
267 void
268 netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si)
269 {
270 memset(si32, 0, sizeof (*si32));
271 si32->si_signo = si->si_signo;
272 si32->si_code = si->si_code;
273 si32->si_errno = si->si_errno;
274
275 switch (si32->si_signo) {
276 case SIGILL:
277 case SIGBUS:
278 case SIGSEGV:
279 case SIGFPE:
280 case SIGTRAP:
281 si32->si_addr = (uint32_t)(uintptr_t)si->si_addr;
282 si32->si_trap = si->si_trap;
283 break;
284 case SIGALRM:
285 case SIGVTALRM:
286 case SIGPROF:
287 si32->si_pid = si->si_pid;
288 si32->si_uid = si->si_uid;
289 /*
290 * XXX sival_ptr is currently unused.
291 */
292 si32->si_sigval.sival_int = si->si_sigval.sival_int;
293 break;
294 case SIGCHLD:
295 si32->si_pid = si->si_pid;
296 si32->si_uid = si->si_uid;
297 si32->si_status = si->si_status;
298 si32->si_utime = si->si_utime;
299 si32->si_stime = si->si_stime;
300 break;
301 case SIGURG:
302 case SIGIO:
303 si32->si_band = si->si_band;
304 si32->si_fd = si->si_fd;
305 break;
306 }
307 }
308
309 void
310 getucontext32(struct lwp *l, ucontext32_t *ucp)
311 {
312 struct proc *p;
313
314 p = l->l_proc;
315
316 ucp->uc_flags = 0;
317 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink;
318
319 (void)sigprocmask1(p, 0, NULL, &ucp->uc_sigmask);
320 ucp->uc_flags |= _UC_SIGMASK;
321
322 /*
323 * The (unsupplied) definition of the `current execution stack'
324 * in the System V Interface Definition appears to allow returning
325 * the main context stack.
326 */
327 if ((p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK) == 0) {
328 ucp->uc_stack.ss_sp = USRSTACK32;
329 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize);
330 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */
331 } else {
332 /* Simply copy alternate signal execution stack. */
333 ucp->uc_stack.ss_sp =
334 (uint32_t)(intptr_t)p->p_sigctx.ps_sigstk.ss_sp;
335 ucp->uc_stack.ss_size = p->p_sigctx.ps_sigstk.ss_size;
336 ucp->uc_stack.ss_flags = p->p_sigctx.ps_sigstk.ss_flags;
337 }
338 ucp->uc_flags |= _UC_STACK;
339
340 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags);
341 }
342
343 /* ARGSUSED */
344 int
345 netbsd32_getcontext(struct lwp *l, void *v, register_t *retval)
346 {
347 struct netbsd32_getcontext_args /* {
348 syscallarg(netbsd32_ucontextp) ucp;
349 } */ *uap = v;
350 ucontext32_t uc;
351
352 getucontext32(l, &uc);
353
354 return copyout(&uc, NETBSD32PTR64(SCARG(uap, ucp)),
355 sizeof (ucontext32_t));
356 }
357
358 int
359 setucontext32(struct lwp *l, const ucontext32_t *ucp)
360 {
361 struct proc *p;
362 int error;
363
364 p = l->l_proc;
365 if ((error = cpu_setmcontext32(l, &ucp->uc_mcontext,
366 ucp->uc_flags)) != 0)
367 return (error);
368 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link;
369 /*
370 * We might want to take care of the stack portion here but currently
371 * don't; see the comment in getucontext().
372 */
373 if ((ucp->uc_flags & _UC_SIGMASK) != 0)
374 sigprocmask1(p, SIG_SETMASK, &ucp->uc_sigmask, NULL);
375
376 return 0;
377 }
378
379 /* ARGSUSED */
380 int
381 netbsd32_setcontext(struct lwp *l, void *v, register_t *retval)
382 {
383 struct netbsd32_setcontext_args /* {
384 syscallarg(netbsd32_ucontextp) ucp;
385 } */ *uap = v;
386 ucontext32_t uc;
387 int error;
388 void *p;
389
390 p = NETBSD32PTR64(SCARG(uap, ucp));
391 if (p == NULL)
392 exit1(l, W_EXITCODE(0, 0));
393 else if ((error = copyin(p, &uc, sizeof (uc))) != 0 ||
394 (error = setucontext32(l, &uc)) != 0)
395 return (error);
396
397 return (EJUSTRETURN);
398 }
399
400 static int
401 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size)
402 {
403 const siginfo_t *info = src;
404 siginfo32_t info32;
405
406 netbsd32_si_to_si32(&info32, info);
407
408 return copyout(&info32, dst, sizeof(info32));
409 }
410
411 static int
412 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size)
413 {
414 struct timespec *ts = dst;
415 struct netbsd32_timespec ts32;
416 int error;
417
418 error = copyin(src, &ts32, sizeof(ts32));
419 if (error)
420 return error;
421
422 netbsd32_to_timespec(&ts32, ts);
423 return 0;
424 }
425
426 static int
427 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size)
428 {
429 const struct timespec *ts = src;
430 struct netbsd32_timespec ts32;
431
432 netbsd32_from_timespec(ts, &ts32);
433
434 return copyout(&ts32, dst, sizeof(ts32));
435 }
436
437 int
438 netbsd32___sigtimedwait(struct lwp *l, void *v, register_t *retval)
439 {
440 struct netbsd32___sigtimedwait_args /* {
441 syscallarg(netbsd32_sigsetp_t) set;
442 syscallarg(netbsd32_siginfop_t) info;
443 syscallarg(netbsd32_timespecp_t) timeout;
444 } */ *uap = v;
445 struct sys___sigtimedwait_args ua;
446
447 NETBSD32TOP_UAP(set, const sigset_t);
448 NETBSD32TOP_UAP(info, siginfo_t);
449 NETBSD32TOP_UAP(timeout, struct timespec);
450
451 return __sigtimedwait1(l, &ua, retval, netbsd32_sigtimedwait_put_info,
452 netbsd32_sigtimedwait_fetch_timeout,
453 netbsd32_sigtimedwait_put_timeout);
454 }
455