1/*-
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/filedesc.h>
35#include <sys/lock.h>
36#include <sys/mutex.h>
37#include <sys/proc.h>
38#include <sys/signal.h>
39#include <sys/signalvar.h>
40#include <sys/syscallsubr.h>
41#include <sys/sysproto.h>
42
43#include <machine/cpu.h>
44
45#include <compat/svr4/svr4.h>
46#include <compat/svr4/svr4_types.h>
47#include <compat/svr4/svr4_signal.h>
48#include <compat/svr4/svr4_proto.h>
49#include <compat/svr4/svr4_util.h>
50#include <compat/svr4/svr4_ucontext.h>
51
52#define	svr4_sigmask(n)		(1 << (((n) - 1) & 31))
53#define	svr4_sigword(n)		(((n) - 1) >> 5)
54#define svr4_sigemptyset(s)	memset((s), 0, sizeof(*(s)))
55#define	svr4_sigismember(s, n)	((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
56#define	svr4_sigaddset(s, n)	((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
57
58void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *);
59void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *);
60void svr4_sigfillset(svr4_sigset_t *);
61
62int bsd_to_svr4_sig[SVR4_NSIG] = {
63	0,
64	SVR4_SIGHUP,
65	SVR4_SIGINT,
66	SVR4_SIGQUIT,
67	SVR4_SIGILL,
68	SVR4_SIGTRAP,
69	SVR4_SIGABRT,
70	SVR4_SIGEMT,
71	SVR4_SIGFPE,
72	SVR4_SIGKILL,
73	SVR4_SIGBUS,
74	SVR4_SIGSEGV,
75	SVR4_SIGSYS,
76	SVR4_SIGPIPE,
77	SVR4_SIGALRM,
78	SVR4_SIGTERM,
79	SVR4_SIGURG,
80	SVR4_SIGSTOP,
81	SVR4_SIGTSTP,
82	SVR4_SIGCONT,
83	SVR4_SIGCHLD,
84	SVR4_SIGTTIN,
85	SVR4_SIGTTOU,
86	SVR4_SIGIO,
87	SVR4_SIGXCPU,
88	SVR4_SIGXFSZ,
89	SVR4_SIGVTALRM,
90	SVR4_SIGPROF,
91	SVR4_SIGWINCH,
92	0,			/* SIGINFO */
93	SVR4_SIGUSR1,
94	SVR4_SIGUSR2,
95};
96
97int svr4_to_bsd_sig[SVR4_NSIG] = {
98	0,
99	SIGHUP,
100	SIGINT,
101	SIGQUIT,
102	SIGILL,
103	SIGTRAP,
104	SIGABRT,
105	SIGEMT,
106	SIGFPE,
107	SIGKILL,
108	SIGBUS,
109	SIGSEGV,
110	SIGSYS,
111	SIGPIPE,
112	SIGALRM,
113	SIGTERM,
114	SIGUSR1,
115	SIGUSR2,
116	SIGCHLD,
117	0,		/* XXX NetBSD uses SIGPWR here, but we don't seem to have one */
118	SIGWINCH,
119	SIGURG,
120	SIGIO,
121	SIGSTOP,
122	SIGTSTP,
123	SIGCONT,
124	SIGTTIN,
125	SIGTTOU,
126	SIGVTALRM,
127	SIGPROF,
128	SIGXCPU,
129	SIGXFSZ,
130};
131
132void
133svr4_sigfillset(s)
134	svr4_sigset_t *s;
135{
136	int i;
137
138	svr4_sigemptyset(s);
139	for (i = 1; i < SVR4_NSIG; i++)
140		if (svr4_to_bsd_sig[i] != 0)
141			svr4_sigaddset(s, i);
142}
143
144void
145svr4_to_bsd_sigset(sss, bss)
146	const svr4_sigset_t *sss;
147	sigset_t *bss;
148{
149	int i, newsig;
150
151	SIGEMPTYSET(*bss);
152	for (i = 1; i < SVR4_NSIG; i++)
153		if (svr4_sigismember(sss, i)) {
154			newsig = svr4_to_bsd_sig[i];
155			if (newsig)
156				SIGADDSET(*bss, newsig);
157		}
158}
159
160void
161bsd_to_svr4_sigset(bss, sss)
162	const sigset_t *bss;
163	svr4_sigset_t *sss;
164{
165	int i, newsig;
166
167	svr4_sigemptyset(sss);
168	for (i = 1; i < SVR4_NSIG; i++) {
169		if (SIGISMEMBER(*bss, i)) {
170			newsig = bsd_to_svr4_sig[i];
171			if (newsig)
172				svr4_sigaddset(sss, newsig);
173		}
174	}
175}
176
177/*
178 * XXX: Only a subset of the flags is currently implemented.
179 */
180void
181svr4_to_bsd_sigaction(ssa, bsa)
182	const struct svr4_sigaction *ssa;
183	struct sigaction *bsa;
184{
185
186	bsa->sa_handler = (sig_t) ssa->ssa_handler;
187	svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask);
188	bsa->sa_flags = 0;
189	if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0)
190		bsa->sa_flags |= SA_ONSTACK;
191	if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0)
192		bsa->sa_flags |= SA_RESETHAND;
193	if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0)
194		bsa->sa_flags |= SA_RESTART;
195	if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0)
196		DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n"));
197	if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0)
198		bsa->sa_flags |= SA_NOCLDSTOP;
199	if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0)
200		bsa->sa_flags |= SA_NODEFER;
201	if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0)
202		bsa->sa_flags |= SA_NOCLDWAIT;
203	if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0)
204		DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n"));
205}
206
207void
208bsd_to_svr4_sigaction(bsa, ssa)
209	const struct sigaction *bsa;
210	struct svr4_sigaction *ssa;
211{
212
213	ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler;
214	bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask);
215	ssa->ssa_flags = 0;
216	if ((bsa->sa_flags & SA_ONSTACK) != 0)
217		ssa->ssa_flags |= SVR4_SA_ONSTACK;
218	if ((bsa->sa_flags & SA_RESETHAND) != 0)
219		ssa->ssa_flags |= SVR4_SA_RESETHAND;
220	if ((bsa->sa_flags & SA_RESTART) != 0)
221		ssa->ssa_flags |= SVR4_SA_RESTART;
222	if ((bsa->sa_flags & SA_NODEFER) != 0)
223		ssa->ssa_flags |= SVR4_SA_NODEFER;
224	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
225		ssa->ssa_flags |= SVR4_SA_NOCLDSTOP;
226}
227
228void
229svr4_to_bsd_sigaltstack(sss, bss)
230	const struct svr4_sigaltstack *sss;
231	struct sigaltstack *bss;
232{
233
234	bss->ss_sp = sss->ss_sp;
235	bss->ss_size = sss->ss_size;
236	bss->ss_flags = 0;
237	if ((sss->ss_flags & SVR4_SS_DISABLE) != 0)
238		bss->ss_flags |= SS_DISABLE;
239	if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0)
240		bss->ss_flags |= SS_ONSTACK;
241	if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0)
242	  /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n");
243}
244
245void
246bsd_to_svr4_sigaltstack(bss, sss)
247	const struct sigaltstack *bss;
248	struct svr4_sigaltstack *sss;
249{
250
251	sss->ss_sp = bss->ss_sp;
252	sss->ss_size = bss->ss_size;
253	sss->ss_flags = 0;
254	if ((bss->ss_flags & SS_DISABLE) != 0)
255		sss->ss_flags |= SVR4_SS_DISABLE;
256	if ((bss->ss_flags & SS_ONSTACK) != 0)
257		sss->ss_flags |= SVR4_SS_ONSTACK;
258}
259
260int
261svr4_sys_sigaction(td, uap)
262	struct thread *td;
263	struct svr4_sys_sigaction_args *uap;
264{
265	struct svr4_sigaction isa;
266	struct sigaction nbsa, obsa;
267	struct sigaction *nbsap;
268	int error;
269
270	if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
271		return (EINVAL);
272
273	DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
274			uap->signum,
275			SVR4_SVR42BSD_SIG(uap->signum)));
276
277	if (uap->nsa != NULL) {
278		if ((error = copyin(uap->nsa, &isa, sizeof(isa))) != 0)
279			return (error);
280		svr4_to_bsd_sigaction(&isa, &nbsa);
281		nbsap = &nbsa;
282	} else
283		nbsap = NULL;
284#if defined(DEBUG_SVR4)
285	{
286		int i;
287		for (i = 0; i < 4; i++)
288			DPRINTF(("\tssa_mask[%d] = %lx\n", i,
289						isa.ssa_mask.bits[i]));
290		DPRINTF(("\tssa_handler = %p\n", isa.ssa_handler));
291	}
292#endif
293	error = kern_sigaction(td, SVR4_SVR42BSD_SIG(uap->signum), nbsap, &obsa,
294	    0);
295	if (error == 0 && uap->osa != NULL) {
296		bsd_to_svr4_sigaction(&obsa, &isa);
297		error = copyout(&isa, uap->osa, sizeof(isa));
298	}
299	return (error);
300}
301
302int
303svr4_sys_sigaltstack(td, uap)
304	struct thread *td;
305	struct svr4_sys_sigaltstack_args *uap;
306{
307	struct svr4_sigaltstack sss;
308	struct sigaltstack nbss, obss, *nbssp;
309	int error;
310
311	if (uap->nss != NULL) {
312		if ((error = copyin(uap->nss, &sss, sizeof(sss))) != 0)
313			return (error);
314		svr4_to_bsd_sigaltstack(&sss, &nbss);
315		nbssp = &nbss;
316	} else
317		nbssp = NULL;
318	error = kern_sigaltstack(td, nbssp, &obss);
319	if (error == 0 && uap->oss != NULL) {
320		bsd_to_svr4_sigaltstack(&obss, &sss);
321		error = copyout(&sss, uap->oss, sizeof(sss));
322	}
323	return (error);
324}
325
326/*
327 * Stolen from the ibcs2 one
328 */
329int
330svr4_sys_signal(td, uap)
331	struct thread *td;
332	struct svr4_sys_signal_args *uap;
333{
334	struct proc *p;
335	int signum;
336	int error;
337
338	p = td->td_proc;
339	DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid));
340
341	signum = SVR4_SIGNO(uap->signum);
342	if (signum < 0 || signum >= SVR4_NSIG) {
343		if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK ||
344		    SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK)
345			td->td_retval[0] = (int)SVR4_SIG_ERR;
346		return (EINVAL);
347	}
348	signum = SVR4_SVR42BSD_SIG(signum);
349
350	switch (SVR4_SIGCALL(uap->signum)) {
351	case SVR4_SIGDEFER_MASK:
352		if (uap->handler == SVR4_SIG_HOLD)
353			goto sighold;
354		/* FALLTHROUGH */
355
356	case SVR4_SIGNAL_MASK:
357		{
358			struct sigaction nbsa, obsa;
359
360			nbsa.sa_handler = (sig_t) uap->handler;
361			SIGEMPTYSET(nbsa.sa_mask);
362			nbsa.sa_flags = 0;
363			if (signum != SIGALRM)
364				nbsa.sa_flags = SA_RESTART;
365			error = kern_sigaction(td, signum, &nbsa, &obsa, 0);
366			if (error != 0) {
367				DPRINTF(("signal: sigaction failed: %d\n",
368					 error));
369				td->td_retval[0] = (int)SVR4_SIG_ERR;
370				return (error);
371			}
372			td->td_retval[0] = (int)obsa.sa_handler;
373			return (0);
374		}
375
376	case SVR4_SIGHOLD_MASK:
377sighold:
378		{
379			sigset_t set;
380
381			SIGEMPTYSET(set);
382			SIGADDSET(set, signum);
383			return (kern_sigprocmask(td, SIG_BLOCK, &set, NULL, 0));
384		}
385
386	case SVR4_SIGRELSE_MASK:
387		{
388			sigset_t set;
389
390			SIGEMPTYSET(set);
391			SIGADDSET(set, signum);
392			return (kern_sigprocmask(td, SIG_UNBLOCK, &set, NULL,
393				    0));
394		}
395
396	case SVR4_SIGIGNORE_MASK:
397		{
398			struct sigaction sa;
399
400			sa.sa_handler = SIG_IGN;
401			SIGEMPTYSET(sa.sa_mask);
402			sa.sa_flags = 0;
403			error = kern_sigaction(td, signum, &sa, NULL, 0);
404			if (error != 0)
405				DPRINTF(("sigignore: sigaction failed\n"));
406			return (error);
407		}
408
409	case SVR4_SIGPAUSE_MASK:
410		{
411			sigset_t mask;
412
413			PROC_LOCK(p);
414			mask = td->td_sigmask;
415			PROC_UNLOCK(p);
416			SIGDELSET(mask, signum);
417			return kern_sigsuspend(td, mask);
418		}
419
420	default:
421		return (ENOSYS);
422	}
423}
424
425
426int
427svr4_sys_sigprocmask(td, uap)
428	struct thread *td;
429	struct svr4_sys_sigprocmask_args *uap;
430{
431	svr4_sigset_t sss;
432	sigset_t oss, nss;
433	sigset_t *nssp;
434	int error;
435
436	if (uap->set != NULL) {
437		if ((error = copyin(uap->set, &sss, sizeof(sss))) != 0)
438			return error;
439		svr4_to_bsd_sigset(&sss, &nss);
440		nssp = &nss;
441	} else
442		nssp = NULL;
443
444	/* SVR/4 sigprocmask flag values are the same as the FreeBSD values. */
445	error = kern_sigprocmask(td, uap->how, nssp, &oss, 0);
446	if (error == 0 && uap->oset != NULL) {
447		bsd_to_svr4_sigset(&oss, &sss);
448		error = copyout(&sss, uap->oset, sizeof(sss));
449	}
450	return (error);
451}
452
453int
454svr4_sys_sigpending(td, uap)
455	struct thread *td;
456	struct svr4_sys_sigpending_args *uap;
457{
458	struct proc *p;
459	sigset_t bss;
460	svr4_sigset_t sss;
461
462	p = td->td_proc;
463	DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", p->p_pid));
464	switch (uap->what) {
465	case 1:	/* sigpending */
466		if (uap->mask == NULL)
467			return 0;
468		PROC_LOCK(p);
469		bss = p->p_siglist;
470		SIGSETOR(bss, td->td_siglist);
471		SIGSETAND(bss, td->td_sigmask);
472		PROC_UNLOCK(p);
473		bsd_to_svr4_sigset(&bss, &sss);
474		break;
475
476	case 2:	/* sigfillset */
477		svr4_sigfillset(&sss);
478#if defined(DEBUG_SVR4)
479		{
480			int i;
481			for (i = 0; i < 4; i++)
482				DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i]));
483		}
484#endif
485		break;
486
487	default:
488		return EINVAL;
489	}
490
491	return copyout(&sss, uap->mask, sizeof(sss));
492}
493
494int
495svr4_sys_sigsuspend(td, uap)
496	struct thread *td;
497	struct svr4_sys_sigsuspend_args *uap;
498{
499	svr4_sigset_t sss;
500	sigset_t bss;
501	int error;
502
503	if ((error = copyin(uap->ss, &sss, sizeof(sss))) != 0)
504		return error;
505
506	svr4_to_bsd_sigset(&sss, &bss);
507	return kern_sigsuspend(td, bss);
508}
509
510
511int
512svr4_sys_kill(td, uap)
513	struct thread *td;
514	struct svr4_sys_kill_args *uap;
515{
516	struct kill_args ka;
517
518	if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
519		return (EINVAL);
520	ka.pid = uap->pid;
521	ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
522	return sys_kill(td, &ka);
523}
524
525
526int
527svr4_sys_context(td, uap)
528	struct thread *td;
529	struct svr4_sys_context_args *uap;
530{
531	struct svr4_ucontext uc;
532	int error, onstack;
533
534	switch (uap->func) {
535	case 0:
536		DPRINTF(("getcontext(%p)\n", uap->uc));
537		PROC_LOCK(td->td_proc);
538		onstack = sigonstack(cpu_getstack(td));
539		PROC_UNLOCK(td->td_proc);
540		svr4_getcontext(td, &uc, &td->td_sigmask, onstack);
541		return copyout(&uc, uap->uc, sizeof(uc));
542
543	case 1:
544		DPRINTF(("setcontext(%p)\n", uap->uc));
545		if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0)
546			return error;
547		DPRINTF(("uc_flags = %lx\n", uc.uc_flags));
548#if defined(DEBUG_SVR4)
549		{
550			int i;
551			for (i = 0; i < 4; i++)
552				DPRINTF(("uc_sigmask[%d] = %lx\n", i,
553							uc.uc_sigmask.bits[i]));
554		}
555#endif
556		return svr4_setcontext(td, &uc);
557
558	default:
559		DPRINTF(("context(%d, %p)\n", uap->func,
560		    uap->uc));
561		return ENOSYS;
562	}
563	return 0;
564}
565
566int
567svr4_sys_pause(td, uap)
568	struct thread *td;
569	struct svr4_sys_pause_args *uap;
570{
571	sigset_t mask;
572
573	PROC_LOCK(td->td_proc);
574	mask = td->td_sigmask;
575	PROC_UNLOCK(td->td_proc);
576	return kern_sigsuspend(td, mask);
577}
578