1/*	$NetBSD: src/sys/compat/svr4/svr4_signal.c,v 1.64 2008-04-28 20:23:45 martin Exp $	 */
2
3/*-
4 * Copyright (c) 1994, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: src/sys/compat/svr4/svr4_signal.c,v 1.64 2008-04-28 20:23:45 martin Exp $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/namei.h>
38#include <sys/proc.h>
39#include <sys/filedesc.h>
40#include <sys/ioctl.h>
41#include <sys/mount.h>
42#include <sys/kernel.h>
43#include <sys/signal.h>
44#include <sys/signalvar.h>
45#include <sys/malloc.h>
46#include <sys/wait.h>
47
48#include <sys/syscallargs.h>
49
50#include <uvm/uvm_extern.h>
51
52#include <compat/svr4/svr4_types.h>
53#include <compat/svr4/svr4_signal.h>
54#include <compat/svr4/svr4_lwp.h>
55#include <compat/svr4/svr4_ucontext.h>
56#include <compat/svr4/svr4_syscallargs.h>
57#include <compat/svr4/svr4_util.h>
58
59#include <compat/common/compat_sigaltstack.h>
60
61#define	svr4_sigmask(n)		(1 << (((n) - 1) & 31))
62#define	svr4_sigword(n)		(((n) - 1) >> 5)
63#define svr4_sigemptyset(s)	memset((s), 0, sizeof(*(s)))
64#define	svr4_sigismember(s, n)	((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
65#define	svr4_sigaddset(s, n)	((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
66
67static inline void svr4_sigfillset(svr4_sigset_t *);
68void svr4_to_native_sigaction(const struct svr4_sigaction *,
69				struct sigaction *);
70void native_to_svr4_sigaction(const struct sigaction *,
71				struct svr4_sigaction *);
72
73extern const int native_to_svr4_signo[];
74extern const int svr4_to_native_signo[];
75
76static inline void
77svr4_sigfillset(svr4_sigset_t *s)
78{
79	int i;
80
81	svr4_sigemptyset(s);
82	for (i = 1; i < SVR4_NSIG; i++)
83		if (svr4_to_native_signo[i] != 0)
84			svr4_sigaddset(s, i);
85}
86
87void
88svr4_to_native_sigset(const svr4_sigset_t *sss, sigset_t *bss)
89{
90	int i, newsig;
91
92	sigemptyset(bss);
93	for (i = 1; i < SVR4_NSIG; i++) {
94		if (svr4_sigismember(sss, i)) {
95			newsig = svr4_to_native_signo[i];
96			if (newsig)
97				sigaddset(bss, newsig);
98		}
99	}
100}
101
102
103void
104native_to_svr4_sigset(const sigset_t *bss, svr4_sigset_t *sss)
105{
106	int i, newsig;
107
108	svr4_sigemptyset(sss);
109	for (i = 1; i < NSIG; i++) {
110		if (sigismember(bss, i)) {
111			newsig = native_to_svr4_signo[i];
112			if (newsig)
113				svr4_sigaddset(sss, newsig);
114		}
115	}
116}
117
118/*
119 * XXX: Only a subset of the flags is currently implemented.
120 */
121void
122svr4_to_native_sigaction(const struct svr4_sigaction *ssa, struct sigaction *bsa)
123{
124
125	bsa->sa_handler = (sig_t) ssa->svr4_sa_handler;
126	svr4_to_native_sigset(&ssa->svr4_sa_mask, &bsa->sa_mask);
127	bsa->sa_flags = 0;
128	if ((ssa->svr4_sa_flags & SVR4_SA_ONSTACK) != 0)
129		bsa->sa_flags |= SA_ONSTACK;
130	if ((ssa->svr4_sa_flags & SVR4_SA_RESETHAND) != 0)
131		bsa->sa_flags |= SA_RESETHAND;
132	if ((ssa->svr4_sa_flags & SVR4_SA_RESTART) != 0)
133		bsa->sa_flags |= SA_RESTART;
134	if ((ssa->svr4_sa_flags & SVR4_SA_SIGINFO) != 0)
135		bsa->sa_flags |= SA_SIGINFO;
136	if ((ssa->svr4_sa_flags & SVR4_SA_NODEFER) != 0)
137		bsa->sa_flags |= SA_NODEFER;
138	if ((ssa->svr4_sa_flags & SVR4_SA_NOCLDWAIT) != 0)
139		bsa->sa_flags |= SA_NOCLDWAIT;
140	if ((ssa->svr4_sa_flags & SVR4_SA_NOCLDSTOP) != 0)
141		bsa->sa_flags |= SA_NOCLDSTOP;
142	if ((ssa->svr4_sa_flags & ~SVR4_SA_ALLBITS) != 0) {
143		DPRINTF(("svr4_to_native_sigaction: extra bits %x ignored\n",
144		    ssa->svr4_sa_flags & ~SVR4_SA_ALLBITS));
145	}
146}
147
148void
149native_to_svr4_sigaction(const struct sigaction *bsa, struct svr4_sigaction *ssa)
150{
151
152	ssa->svr4_sa_handler = (svr4_sig_t) bsa->sa_handler;
153	native_to_svr4_sigset(&bsa->sa_mask, &ssa->svr4_sa_mask);
154	ssa->svr4_sa_flags = 0;
155	if ((bsa->sa_flags & SA_ONSTACK) != 0)
156		ssa->svr4_sa_flags |= SVR4_SA_ONSTACK;
157	if ((bsa->sa_flags & SA_RESETHAND) != 0)
158		ssa->svr4_sa_flags |= SVR4_SA_RESETHAND;
159	if ((bsa->sa_flags & SA_RESTART) != 0)
160		ssa->svr4_sa_flags |= SVR4_SA_RESTART;
161	if ((bsa->sa_flags & SA_NODEFER) != 0)
162		ssa->svr4_sa_flags |= SVR4_SA_NODEFER;
163	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
164		ssa->svr4_sa_flags |= SVR4_SA_NOCLDSTOP;
165}
166
167int
168svr4_sys_sigaction(struct lwp *l, const struct svr4_sys_sigaction_args *uap, register_t *retval)
169{
170	/* {
171		syscallarg(int) signum;
172		syscallarg(const struct svr4_sigaction *) nsa;
173		syscallarg(struct svr4_sigaction *) osa;
174	} */
175	struct svr4_sigaction nssa, ossa;
176	struct sigaction nbsa, obsa;
177	int error;
178
179	if (SCARG(uap, nsa)) {
180		error = copyin(SCARG(uap, nsa), &nssa, sizeof(nssa));
181		if (error)
182			return (error);
183		svr4_to_native_sigaction(&nssa, &nbsa);
184	}
185	error = sigaction1(l, svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))],
186	    SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0,
187	    NULL, 0);
188	if (error)
189		return (error);
190	if (SCARG(uap, osa)) {
191		native_to_svr4_sigaction(&obsa, &ossa);
192		error = copyout(&ossa, SCARG(uap, osa), sizeof(ossa));
193		if (error)
194			return (error);
195	}
196	return (0);
197}
198
199int
200svr4_sys_sigaltstack(struct lwp *l, const struct svr4_sys_sigaltstack_args *uap, register_t *retval)
201{
202	/* {
203		syscallarg(const struct svr4_sigaltstack *) nss;
204		syscallarg(struct svr4_sigaltstack *) oss;
205	} */
206	compat_sigaltstack(uap, svr4_sigaltstack,
207	    SVR4_SS_ONSTACK, SVR4_SS_DISABLE);
208}
209
210/*
211 * Stolen from the ibcs2 one
212 */
213int
214svr4_sys_signal(struct lwp *l, const struct svr4_sys_signal_args *uap, register_t *retval)
215{
216	/* {
217		syscallarg(int) signum;
218		syscallarg(svr4_sig_t) handler;
219	} */
220	int signum = svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))];
221	struct proc *p = l->l_proc;
222	struct sigaction nbsa, obsa;
223	sigset_t ss;
224	int error;
225
226	if (signum <= 0 || signum >= SVR4_NSIG)
227		return (EINVAL);
228
229	switch (SVR4_SIGCALL(SCARG(uap, signum))) {
230	case SVR4_SIGDEFER_MASK:
231		if (SCARG(uap, handler) == SVR4_SIG_HOLD)
232			goto sighold;
233		/* FALLTHROUGH */
234
235	case SVR4_SIGNAL_MASK:
236		nbsa.sa_handler = (sig_t)SCARG(uap, handler);
237		sigemptyset(&nbsa.sa_mask);
238		nbsa.sa_flags = 0;
239		error = sigaction1(l, signum, &nbsa, &obsa, NULL, 0);
240		if (error)
241			return (error);
242		*retval = (u_int)(u_long)obsa.sa_handler;
243		return (0);
244
245	case SVR4_SIGHOLD_MASK:
246	sighold:
247		sigemptyset(&ss);
248		sigaddset(&ss, signum);
249		mutex_enter(p->p_lock);
250		error = sigprocmask1(l, SIG_BLOCK, &ss, 0);
251		mutex_exit(p->p_lock);
252		return error;
253
254	case SVR4_SIGRELSE_MASK:
255		sigemptyset(&ss);
256		sigaddset(&ss, signum);
257		mutex_enter(p->p_lock);
258		error = sigprocmask1(l, SIG_UNBLOCK, &ss, 0);
259		mutex_exit(p->p_lock);
260		return error;
261
262	case SVR4_SIGIGNORE_MASK:
263		nbsa.sa_handler = SIG_IGN;
264		sigemptyset(&nbsa.sa_mask);
265		nbsa.sa_flags = 0;
266		return (sigaction1(l, signum, &nbsa, 0, NULL, 0));
267
268	case SVR4_SIGPAUSE_MASK:
269		ss = l->l_sigmask;	/* XXXAD locking */
270		sigdelset(&ss, signum);
271		return (sigsuspend1(l, &ss));
272
273	default:
274		return (ENOSYS);
275	}
276}
277
278int
279svr4_sys_sigprocmask(struct lwp *l, const struct svr4_sys_sigprocmask_args *uap, register_t *retval)
280{
281	/* {
282		syscallarg(int) how;
283		syscallarg(const svr4_sigset_t *) set;
284		syscallarg(svr4_sigset_t *) oset;
285	} */
286	struct proc *p = l->l_proc;
287	svr4_sigset_t nsss, osss;
288	sigset_t nbss, obss;
289	int how;
290	int error;
291
292	/*
293	 * Initialize how to 0 to avoid a compiler warning.  Note that
294	 * this is safe because of the check in the default: case.
295	 */
296	how = 0;
297
298	switch (SCARG(uap, how)) {
299	case SVR4_SIG_BLOCK:
300		how = SIG_BLOCK;
301		break;
302	case SVR4_SIG_UNBLOCK:
303		how = SIG_UNBLOCK;
304		break;
305	case SVR4_SIG_SETMASK:
306		how = SIG_SETMASK;
307		break;
308	default:
309		if (SCARG(uap, set))
310			return EINVAL;
311		break;
312	}
313
314	if (SCARG(uap, set)) {
315		error = copyin(SCARG(uap, set), &nsss, sizeof(nsss));
316		if (error)
317			return error;
318		svr4_to_native_sigset(&nsss, &nbss);
319	}
320	mutex_enter(p->p_lock);
321	error = sigprocmask1(l, how,
322	    SCARG(uap, set) ? &nbss : NULL, SCARG(uap, oset) ? &obss : NULL);
323	mutex_exit(p->p_lock);
324	if (error)
325		return error;
326	if (SCARG(uap, oset)) {
327		native_to_svr4_sigset(&obss, &osss);
328		error = copyout(&osss, SCARG(uap, oset), sizeof(osss));
329		if (error)
330			return error;
331	}
332	return 0;
333}
334
335int
336svr4_sys_sigpending(struct lwp *l, const struct svr4_sys_sigpending_args *uap, register_t *retval)
337{
338	/* {
339		syscallarg(int) what;
340		syscallarg(svr4_sigset_t *) set;
341	} */
342	sigset_t bss;
343	svr4_sigset_t sss;
344
345	switch (SCARG(uap, what)) {
346	case 1:	/* sigpending */
347		sigpending1(l, &bss);
348		native_to_svr4_sigset(&bss, &sss);
349		break;
350
351	case 2:	/* sigfillset */
352		svr4_sigfillset(&sss);
353		break;
354
355	default:
356		return (EINVAL);
357	}
358	return (copyout(&sss, SCARG(uap, set), sizeof(sss)));
359}
360
361int
362svr4_sys_sigsuspend(struct lwp *l, const struct svr4_sys_sigsuspend_args *uap, register_t *retval)
363{
364	/* {
365		syscallarg(const svr4_sigset_t *) set;
366	} */
367	svr4_sigset_t sss;
368	sigset_t bss;
369	int error;
370
371	if (SCARG(uap, set)) {
372		error = copyin(SCARG(uap, set), &sss, sizeof(sss));
373		if (error)
374			return (error);
375		svr4_to_native_sigset(&sss, &bss);
376	}
377
378	return (sigsuspend1(l, SCARG(uap, set) ? &bss : 0));
379}
380
381int
382svr4_sys_pause(struct lwp *l, const void *v, register_t *retval)
383{
384
385	return (sigsuspend1(l, 0));
386}
387
388int
389svr4_sys_kill(struct lwp *l, const struct svr4_sys_kill_args *uap, register_t *retval)
390{
391	/* {
392		syscallarg(int) pid;
393		syscallarg(int) signum;
394	} */
395	struct sys_kill_args ka;
396
397	SCARG(&ka, pid) = SCARG(uap, pid);
398	SCARG(&ka, signum) = svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))];
399	return sys_kill(l, &ka, retval);
400}
401
402void
403svr4_getcontext(struct lwp *l, struct svr4_ucontext *uc)
404{
405	sigset_t mask;
406	struct proc *p = l->l_proc;
407
408	svr4_getmcontext(l, &uc->uc_mcontext, &uc->uc_flags);
409	uc->uc_link = l->l_ctxlink;
410
411	/*
412	 * The (unsupplied) definition of the `current execution stack'
413	 * in the System V Interface Definition appears to allow returning
414	 * the main context stack.
415	 */
416	if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) {
417		uc->uc_stack.ss_sp = (void *)USRSTACK;
418		uc->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize);
419		uc->uc_stack.ss_flags = 0;	/* XXX, def. is Very Fishy */
420	} else {
421		/* Simply copy alternate signal execution stack. */
422		uc->uc_stack.ss_sp = l->l_sigstk.ss_sp;
423		uc->uc_stack.ss_size = l->l_sigstk.ss_size;
424		uc->uc_stack.ss_flags = l->l_sigstk.ss_flags;
425	}
426	(void)sigprocmask1(l, 0, NULL, &mask);
427
428	native_to_svr4_sigset(&mask, &uc->uc_sigmask);
429	uc->uc_flags |= _UC_SIGMASK | _UC_STACK;
430}
431
432
433int
434svr4_setcontext(struct lwp *l, struct svr4_ucontext *uc)
435{
436	struct proc *p = l->l_proc;
437	sigset_t mask;
438
439	if (uc->uc_flags & _UC_SIGMASK) {
440		svr4_to_native_sigset(&uc->uc_sigmask, &mask);
441		mutex_enter(p->p_lock);
442		sigprocmask1(l, SIG_SETMASK, &mask, NULL);
443		mutex_exit(p->p_lock);
444	}
445
446	/* Ignore the stack; see comment in svr4_getcontext. */
447
448	l->l_ctxlink = uc->uc_link;
449	svr4_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
450
451	return EJUSTRETURN;
452}
453
454int
455svr4_sys_context(struct lwp *l, const struct svr4_sys_context_args *uap, register_t *retval)
456{
457	/* {
458		syscallarg(int) func;
459		syscallarg(struct svr4_ucontext *) uc;
460	} */
461	int error;
462	svr4_ucontext_t uc;
463	*retval = 0;
464
465	memset(&uc, 0, sizeof(uc));
466
467	switch (SCARG(uap, func)) {
468	case SVR4_GETCONTEXT:
469		DPRINTF(("getcontext(%p)\n", SCARG(uap, uc)));
470		svr4_getcontext(l, &uc);
471	return (copyout(&uc, SCARG(uap, uc), sizeof (*SCARG(uap, uc))));
472
473
474	case SVR4_SETCONTEXT:
475		DPRINTF(("setcontext(%p)\n", SCARG(uap, uc)));
476		error = copyin(SCARG(uap, uc), &uc, sizeof (uc));
477		if (error)
478			return (error);
479		svr4_setcontext(l, &uc);
480		return EJUSTRETURN;
481
482	default:
483		DPRINTF(("context(%d, %p)\n", SCARG(uap, func),
484		    SCARG(uap, uc)));
485		return ENOSYS;
486	}
487}
488