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