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