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