svr4_signal.c revision 121275
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: head/sys/compat/svr4/svr4_signal.c 121275 2003-10-20 10:38:48Z tjr $");
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_SIGTBLSZ] = {
63	SVR4_SIGHUP,
64	SVR4_SIGINT,
65	SVR4_SIGQUIT,
66	SVR4_SIGILL,
67	SVR4_SIGTRAP,
68	SVR4_SIGABRT,
69	SVR4_SIGEMT,
70	SVR4_SIGFPE,
71	SVR4_SIGKILL,
72	SVR4_SIGBUS,
73	SVR4_SIGSEGV,
74	SVR4_SIGSYS,
75	SVR4_SIGPIPE,
76	SVR4_SIGALRM,
77	SVR4_SIGTERM,
78	SVR4_SIGURG,
79	SVR4_SIGSTOP,
80	SVR4_SIGTSTP,
81	SVR4_SIGCONT,
82	SVR4_SIGCHLD,
83	SVR4_SIGTTIN,
84	SVR4_SIGTTOU,
85	SVR4_SIGIO,
86	SVR4_SIGXCPU,
87	SVR4_SIGXFSZ,
88	SVR4_SIGVTALRM,
89	SVR4_SIGPROF,
90	SVR4_SIGWINCH,
91	0,			/* SIGINFO */
92	SVR4_SIGUSR1,
93	SVR4_SIGUSR2,
94};
95
96int svr4_to_bsd_sig[SVR4_SIGTBLSZ] = {
97	SIGHUP,
98	SIGINT,
99	SIGQUIT,
100	SIGILL,
101	SIGTRAP,
102	SIGABRT,
103	SIGEMT,
104	SIGFPE,
105	SIGKILL,
106	SIGBUS,
107	SIGSEGV,
108	SIGSYS,
109	SIGPIPE,
110	SIGALRM,
111	SIGTERM,
112	SIGUSR1,
113	SIGUSR2,
114	SIGCHLD,
115	0,		/* XXX NetBSD uses SIGPWR here, but we don't seem to have one */
116	SIGWINCH,
117	SIGURG,
118	SIGIO,
119	SIGSTOP,
120	SIGTSTP,
121	SIGCONT,
122	SIGTTIN,
123	SIGTTOU,
124	SIGVTALRM,
125	SIGPROF,
126	SIGXCPU,
127	SIGXFSZ,
128};
129
130void
131svr4_sigfillset(s)
132	svr4_sigset_t *s;
133{
134	int i;
135
136	svr4_sigemptyset(s);
137	for (i = 0; i < SVR4_NSIG; i++)
138		if (svr4_to_bsd_sig[i] != 0)
139			svr4_sigaddset(s, i);
140}
141
142void
143svr4_to_bsd_sigset(sss, bss)
144	const svr4_sigset_t *sss;
145	sigset_t *bss;
146{
147	int i, newsig;
148
149	SIGEMPTYSET(*bss);
150	for (i = 0; i < SVR4_NSIG; i++)
151		if (svr4_sigismember(sss, i + 1)) {
152			newsig = svr4_to_bsd_sig[i];
153			if (newsig)
154				SIGADDSET(*bss, newsig);
155		}
156}
157
158void
159bsd_to_svr4_sigset(bss, sss)
160	const sigset_t *bss;
161	svr4_sigset_t *sss;
162{
163	int i, newsig;
164
165	svr4_sigemptyset(sss);
166	sss->bits[0] = bss->__bits[0] & ~((1U << SVR4_SIGTBLSZ) - 1);
167	sss->bits[1] = bss->__bits[1];
168	sss->bits[2] = bss->__bits[2];
169	sss->bits[3] = bss->__bits[3];
170	for (i = 1; i <= SVR4_SIGTBLSZ; i++) {
171		if (SIGISMEMBER(*bss, i)) {
172			newsig = bsd_to_svr4_sig[_SIG_IDX(i)];
173			if (newsig)
174				svr4_sigaddset(sss, newsig);
175		}
176	}
177}
178
179/*
180 * XXX: Only a subset of the flags is currently implemented.
181 */
182void
183svr4_to_bsd_sigaction(ssa, bsa)
184	const struct svr4_sigaction *ssa;
185	struct sigaction *bsa;
186{
187
188	bsa->sa_handler = (sig_t) ssa->ssa_handler;
189	svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask);
190	bsa->sa_flags = 0;
191	if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0)
192		bsa->sa_flags |= SA_ONSTACK;
193	if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0)
194		bsa->sa_flags |= SA_RESETHAND;
195	if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0)
196		bsa->sa_flags |= SA_RESTART;
197	if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0)
198		DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n"));
199	if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0)
200		bsa->sa_flags |= SA_NOCLDSTOP;
201	if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0)
202		bsa->sa_flags |= SA_NODEFER;
203	if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0)
204		bsa->sa_flags |= SA_NOCLDWAIT;
205	if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0)
206		DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n"));
207}
208
209void
210bsd_to_svr4_sigaction(bsa, ssa)
211	const struct sigaction *bsa;
212	struct svr4_sigaction *ssa;
213{
214
215	ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler;
216	bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask);
217	ssa->ssa_flags = 0;
218	if ((bsa->sa_flags & SA_ONSTACK) != 0)
219		ssa->ssa_flags |= SVR4_SA_ONSTACK;
220	if ((bsa->sa_flags & SA_RESETHAND) != 0)
221		ssa->ssa_flags |= SVR4_SA_RESETHAND;
222	if ((bsa->sa_flags & SA_RESTART) != 0)
223		ssa->ssa_flags |= SVR4_SA_RESTART;
224	if ((bsa->sa_flags & SA_NODEFER) != 0)
225		ssa->ssa_flags |= SVR4_SA_NODEFER;
226	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
227		ssa->ssa_flags |= SVR4_SA_NOCLDSTOP;
228}
229
230void
231svr4_to_bsd_sigaltstack(sss, bss)
232	const struct svr4_sigaltstack *sss;
233	struct sigaltstack *bss;
234{
235
236	bss->ss_sp = sss->ss_sp;
237	bss->ss_size = sss->ss_size;
238	bss->ss_flags = 0;
239	if ((sss->ss_flags & SVR4_SS_DISABLE) != 0)
240		bss->ss_flags |= SS_DISABLE;
241	if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0)
242		bss->ss_flags |= SS_ONSTACK;
243	if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0)
244	  /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n");
245}
246
247void
248bsd_to_svr4_sigaltstack(bss, sss)
249	const struct sigaltstack *bss;
250	struct svr4_sigaltstack *sss;
251{
252
253	sss->ss_sp = bss->ss_sp;
254	sss->ss_size = bss->ss_size;
255	sss->ss_flags = 0;
256	if ((bss->ss_flags & SS_DISABLE) != 0)
257		sss->ss_flags |= SVR4_SS_DISABLE;
258	if ((bss->ss_flags & SS_ONSTACK) != 0)
259		sss->ss_flags |= SVR4_SS_ONSTACK;
260}
261
262int
263svr4_sys_sigaction(td, uap)
264	register struct thread *td;
265	struct svr4_sys_sigaction_args *uap;
266{
267	struct svr4_sigaction isa;
268	struct sigaction nbsa, obsa;
269	struct sigaction *nbsap;
270	int error;
271
272	if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
273		return (EINVAL);
274
275	DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
276			uap->signum,
277			SVR4_SVR42BSD_SIG(uap->signum)));
278
279	if (uap->nsa != NULL) {
280		if ((error = copyin(uap->nsa, &isa, sizeof(isa))) != 0)
281			return (error);
282		svr4_to_bsd_sigaction(&isa, &nbsa);
283		nbsap = &nbsa;
284	} else
285		nbsap = NULL;
286#if defined(DEBUG_SVR4)
287	{
288		int i;
289		for (i = 0; i < 4; i++)
290			DPRINTF(("\tssa_mask[%d] = %lx\n", i,
291						isa.ssa_mask.bits[i]));
292		DPRINTF(("\tssa_handler = %p\n", isa.ssa_handler));
293	}
294#endif
295	error = kern_sigaction(td, SVR4_SVR42BSD_SIG(uap->signum), nbsap, &obsa,
296	    0);
297	if (error == 0 && uap->osa != NULL) {
298		bsd_to_svr4_sigaction(&obsa, &isa);
299		error = copyout(&isa, uap->osa, sizeof(isa));
300	}
301	return (error);
302}
303
304int
305svr4_sys_sigaltstack(td, uap)
306	register struct thread *td;
307	struct svr4_sys_sigaltstack_args *uap;
308{
309	struct svr4_sigaltstack sss;
310	struct sigaltstack nbss, obss, *nbssp;
311	int error;
312
313	if (uap->nss != NULL) {
314		if ((error = copyin(uap->nss, &sss, sizeof(sss))) != 0)
315			return (error);
316		svr4_to_bsd_sigaltstack(&sss, &nbss);
317		nbssp = &nbss;
318	} else
319		nbssp = NULL;
320	error = kern_sigaltstack(td, nbssp, &obss);
321	if (error == 0 && uap->oss != NULL) {
322		bsd_to_svr4_sigaltstack(&obss, &sss);
323		error = copyout(&sss, uap->oss, sizeof(sss));
324	}
325	return (error);
326}
327
328/*
329 * Stolen from the ibcs2 one
330 */
331int
332svr4_sys_signal(td, uap)
333	register struct thread *td;
334	struct svr4_sys_signal_args *uap;
335{
336	struct proc *p;
337	int signum;
338	int error;
339
340	p = td->td_proc;
341	DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid));
342
343	signum = SVR4_SIGNO(uap->signum);
344	if (signum < 0 || signum >= SVR4_NSIG) {
345		if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK ||
346		    SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK)
347			td->td_retval[0] = (int)SVR4_SIG_ERR;
348		return (EINVAL);
349	}
350	signum = SVR4_SVR42BSD_SIG(signum);
351
352	switch (SVR4_SIGCALL(uap->signum)) {
353	case SVR4_SIGDEFER_MASK:
354		if (uap->handler == SVR4_SIG_HOLD)
355			goto sighold;
356		/* FALLTHROUGH */
357
358	case SVR4_SIGNAL_MASK:
359		{
360			struct sigaction nbsa, obsa;
361
362			nbsa.sa_handler = (sig_t) uap->handler;
363			SIGEMPTYSET(nbsa.sa_mask);
364			nbsa.sa_flags = 0;
365			if (signum != SIGALRM)
366				nbsa.sa_flags = SA_RESTART;
367			error = kern_sigaction(td, signum, &nbsa, &obsa, 0);
368			if (error != 0) {
369				DPRINTF(("signal: sigaction failed: %d\n",
370					 error));
371				td->td_retval[0] = (int)SVR4_SIG_ERR;
372				return (error);
373			}
374			td->td_retval[0] = (int)obsa.sa_handler;
375			return (0);
376		}
377
378	case SVR4_SIGHOLD_MASK:
379sighold:
380		{
381			sigset_t set;
382
383			SIGEMPTYSET(set);
384			SIGADDSET(set, signum);
385			return (kern_sigprocmask(td, SIG_BLOCK, &set, NULL, 0));
386		}
387
388	case SVR4_SIGRELSE_MASK:
389		{
390			sigset_t set;
391
392			SIGEMPTYSET(set);
393			SIGADDSET(set, signum);
394			return (kern_sigprocmask(td, SIG_UNBLOCK, &set, NULL,
395				    0));
396		}
397
398	case SVR4_SIGIGNORE_MASK:
399		{
400			struct sigaction sa;
401
402			sa.sa_handler = SIG_IGN;
403			SIGEMPTYSET(sa.sa_mask);
404			sa.sa_flags = 0;
405			error = kern_sigaction(td, signum, &sa, NULL, 0);
406			if (error != 0)
407				DPRINTF(("sigignore: sigaction failed\n"));
408			return (error);
409		}
410
411	case SVR4_SIGPAUSE_MASK:
412		{
413			sigset_t mask;
414
415			PROC_LOCK(p);
416			mask = td->td_sigmask;
417			PROC_UNLOCK(p);
418			SIGDELSET(mask, signum);
419			return kern_sigsuspend(td, mask);
420		}
421
422	default:
423		return (ENOSYS);
424	}
425}
426
427
428int
429svr4_sys_sigprocmask(td, uap)
430	struct thread *td;
431	struct svr4_sys_sigprocmask_args *uap;
432{
433	svr4_sigset_t sss;
434	sigset_t oss, nss;
435	sigset_t *nssp;
436	int error;
437
438	if (uap->set != NULL) {
439		if ((error = copyin(uap->set, &sss, sizeof(sss))) != 0)
440			return error;
441		svr4_to_bsd_sigset(&sss, &nss);
442		nssp = &nss;
443	} else
444		nssp = NULL;
445
446	/* SVR/4 sigprocmask flag values are the same as the FreeBSD values. */
447	error = kern_sigprocmask(td, uap->how, nssp, &oss, 0);
448	if (error == 0 && uap->oset != NULL) {
449		bsd_to_svr4_sigset(&oss, &sss);
450		error = copyout(&sss, uap->oset, sizeof(sss));
451	}
452	return (error);
453}
454
455int
456svr4_sys_sigpending(td, uap)
457	struct thread *td;
458	struct svr4_sys_sigpending_args *uap;
459{
460	struct proc *p;
461	sigset_t bss;
462	svr4_sigset_t sss;
463
464	p = td->td_proc;
465	DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", p->p_pid));
466	switch (uap->what) {
467	case 1:	/* sigpending */
468		if (uap->mask == NULL)
469			return 0;
470		PROC_LOCK(p);
471		bss = p->p_siglist;
472		SIGSETOR(bss, td->td_siglist);
473		SIGSETAND(bss, td->td_sigmask);
474		PROC_UNLOCK(p);
475		bsd_to_svr4_sigset(&bss, &sss);
476		break;
477
478	case 2:	/* sigfillset */
479		svr4_sigfillset(&sss);
480#if defined(DEBUG_SVR4)
481		{
482			int i;
483			for (i = 0; i < 4; i++)
484				DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i]));
485		}
486#endif
487		break;
488
489	default:
490		return EINVAL;
491	}
492
493	return copyout(&sss, uap->mask, sizeof(sss));
494}
495
496int
497svr4_sys_sigsuspend(td, uap)
498	register struct thread *td;
499	struct svr4_sys_sigsuspend_args *uap;
500{
501	svr4_sigset_t sss;
502	sigset_t bss;
503	int error;
504
505	if ((error = copyin(uap->ss, &sss, sizeof(sss))) != 0)
506		return error;
507
508	svr4_to_bsd_sigset(&sss, &bss);
509	return kern_sigsuspend(td, bss);
510}
511
512
513int
514svr4_sys_kill(td, uap)
515	register struct thread *td;
516	struct svr4_sys_kill_args *uap;
517{
518	struct kill_args ka;
519
520	if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
521		return (EINVAL);
522	ka.pid = uap->pid;
523	ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
524	return kill(td, &ka);
525}
526
527
528int
529svr4_sys_context(td, uap)
530	register struct thread *td;
531	struct svr4_sys_context_args *uap;
532{
533	struct svr4_ucontext uc;
534	int error, onstack;
535
536	switch (uap->func) {
537	case 0:
538		DPRINTF(("getcontext(%p)\n", uap->uc));
539		PROC_LOCK(td->td_proc);
540		onstack = sigonstack(cpu_getstack(td));
541		PROC_UNLOCK(td->td_proc);
542		svr4_getcontext(td, &uc, &td->td_sigmask, onstack);
543		return copyout(&uc, uap->uc, sizeof(uc));
544
545	case 1:
546		DPRINTF(("setcontext(%p)\n", uap->uc));
547		if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0)
548			return error;
549		DPRINTF(("uc_flags = %lx\n", uc.uc_flags));
550#if defined(DEBUG_SVR4)
551		{
552			int i;
553			for (i = 0; i < 4; i++)
554				DPRINTF(("uc_sigmask[%d] = %lx\n", i,
555							uc.uc_sigmask.bits[i]));
556		}
557#endif
558		return svr4_setcontext(td, &uc);
559
560	default:
561		DPRINTF(("context(%d, %p)\n", uap->func,
562		    uap->uc));
563		return ENOSYS;
564	}
565	return 0;
566}
567
568int
569svr4_sys_pause(td, uap)
570	register struct thread *td;
571	struct svr4_sys_pause_args *uap;
572{
573	sigset_t mask;
574
575	PROC_LOCK(td->td_proc);
576	mask = td->td_sigmask;
577	PROC_UNLOCK(td->td_proc);
578	return kern_sigsuspend(td, mask);
579}
580