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