linux_signal.c revision 72543
19313Ssos/*-
29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt
39313Ssos * All rights reserved.
49313Ssos *
59313Ssos * Redistribution and use in source and binary forms, with or without
69313Ssos * modification, are permitted provided that the following conditions
79313Ssos * are met:
89313Ssos * 1. Redistributions of source code must retain the above copyright
99313Ssos *    notice, this list of conditions and the following disclaimer
109313Ssos *    in this position and unchanged.
119313Ssos * 2. Redistributions in binary form must reproduce the above copyright
129313Ssos *    notice, this list of conditions and the following disclaimer in the
139313Ssos *    documentation and/or other materials provided with the distribution.
149313Ssos * 3. The name of the author may not be used to endorse or promote products
159313Ssos *    derived from this software withough specific prior written permission
169313Ssos *
179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279313Ssos *
2850477Speter * $FreeBSD: head/sys/compat/linux/linux_signal.c 72543 2001-02-16 16:40:43Z jlemon $
299313Ssos */
309313Ssos
319313Ssos#include <sys/param.h>
329313Ssos#include <sys/systm.h>
3312458Sbde#include <sys/sysproto.h>
349313Ssos#include <sys/proc.h>
359313Ssos#include <sys/signalvar.h>
369313Ssos
3764911Smarcel#include <machine/../linux/linux.h>
3868583Smarcel#include <machine/../linux/linux_proto.h>
3964911Smarcel#include <compat/linux/linux_signal.h>
4064911Smarcel#include <compat/linux/linux_util.h>
419313Ssos
4264911Smarcelvoid
4351793Smarcellinux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss)
4451793Smarcel{
4551793Smarcel	int b, l;
469313Ssos
4751793Smarcel	SIGEMPTYSET(*bss);
4851793Smarcel	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
4951793Smarcel	bss->__bits[1] = lss->__bits[1];
5051793Smarcel	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
5151793Smarcel		if (LINUX_SIGISMEMBER(*lss, l)) {
5268201Sobrien#ifdef __alpha__
5368201Sobrien			b = _SIG_IDX(l);
5468201Sobrien#else
5551793Smarcel			b = linux_to_bsd_signal[_SIG_IDX(l)];
5668201Sobrien#endif
5751793Smarcel			if (b)
5851793Smarcel				SIGADDSET(*bss, b);
5951793Smarcel		}
6014331Speter	}
619313Ssos}
629313Ssos
6367234Sgallatinvoid
6451793Smarcelbsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss)
6551793Smarcel{
6651793Smarcel	int b, l;
679313Ssos
6851793Smarcel	LINUX_SIGEMPTYSET(*lss);
6951793Smarcel	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
7051793Smarcel	lss->__bits[1] = bss->__bits[1];
7151793Smarcel	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
7251793Smarcel		if (SIGISMEMBER(*bss, b)) {
7368201Sobrien#if __alpha__
7468201Sobrien			l = _SIG_IDX(b);
7568201Sobrien#else
7651793Smarcel			l = bsd_to_linux_signal[_SIG_IDX(b)];
7768201Sobrien#endif
7851793Smarcel			if (l)
7951793Smarcel				LINUX_SIGADDSET(*lss, l);
8051793Smarcel		}
8114331Speter	}
829313Ssos}
839313Ssos
8414342Speterstatic void
8514331Speterlinux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa)
8614331Speter{
8751793Smarcel
8851793Smarcel	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
8951793Smarcel	bsa->sa_handler = lsa->lsa_handler;
9051793Smarcel	bsa->sa_flags = 0;
9151793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
9251793Smarcel		bsa->sa_flags |= SA_NOCLDSTOP;
9351793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
9451793Smarcel		bsa->sa_flags |= SA_NOCLDWAIT;
9551793Smarcel	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
9651793Smarcel		bsa->sa_flags |= SA_SIGINFO;
9751793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
9851793Smarcel		bsa->sa_flags |= SA_ONSTACK;
9951793Smarcel	if (lsa->lsa_flags & LINUX_SA_RESTART)
10051793Smarcel		bsa->sa_flags |= SA_RESTART;
10151793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
10251793Smarcel		bsa->sa_flags |= SA_RESETHAND;
10351793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOMASK)
10451793Smarcel		bsa->sa_flags |= SA_NODEFER;
10514331Speter}
1069313Ssos
10714342Speterstatic void
10814331Speterbsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa)
10914331Speter{
11051793Smarcel
11151793Smarcel	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
11251793Smarcel	lsa->lsa_handler = bsa->sa_handler;
11351793Smarcel	lsa->lsa_restorer = NULL;	/* unsupported */
11451793Smarcel	lsa->lsa_flags = 0;
11551793Smarcel	if (bsa->sa_flags & SA_NOCLDSTOP)
11651793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
11751793Smarcel	if (bsa->sa_flags & SA_NOCLDWAIT)
11851793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
11951793Smarcel	if (bsa->sa_flags & SA_SIGINFO)
12051793Smarcel		lsa->lsa_flags |= LINUX_SA_SIGINFO;
12151793Smarcel	if (bsa->sa_flags & SA_ONSTACK)
12251793Smarcel		lsa->lsa_flags |= LINUX_SA_ONSTACK;
12351793Smarcel	if (bsa->sa_flags & SA_RESTART)
12451793Smarcel		lsa->lsa_flags |= LINUX_SA_RESTART;
12551793Smarcel	if (bsa->sa_flags & SA_RESETHAND)
12651793Smarcel		lsa->lsa_flags |= LINUX_SA_ONESHOT;
12751793Smarcel	if (bsa->sa_flags & SA_NODEFER)
12851793Smarcel		lsa->lsa_flags |= LINUX_SA_NOMASK;
12914331Speter}
13014331Speter
13164911Smarcelint
13249786Smarcellinux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa,
13349786Smarcel		   linux_sigaction_t *linux_osa)
13449786Smarcel{
13553954Smarcel	struct sigaction *nsa, *osa;
13651793Smarcel	struct sigaction_args sa_args;
13751793Smarcel	int error;
13851793Smarcel	caddr_t sg = stackgap_init();
13949786Smarcel
14051793Smarcel	if (linux_sig <= 0 || linux_sig > LINUX_NSIG)
14151793Smarcel		return (EINVAL);
14249786Smarcel
14351793Smarcel	if (linux_osa != NULL)
14451793Smarcel		osa = stackgap_alloc(&sg, sizeof(struct sigaction));
14551793Smarcel	else
14651793Smarcel		osa = NULL;
14749786Smarcel
14851793Smarcel	if (linux_nsa != NULL) {
14951793Smarcel		nsa = stackgap_alloc(&sg, sizeof(struct sigaction));
15053954Smarcel		linux_to_bsd_sigaction(linux_nsa, nsa);
15151793Smarcel	}
15251793Smarcel	else
15351793Smarcel		nsa = NULL;
15449786Smarcel
15568201Sobrien#ifndef __alpha__
15651793Smarcel	if (linux_sig <= LINUX_SIGTBLSZ)
15751793Smarcel		sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
15851793Smarcel	else
15968201Sobrien#endif
16051793Smarcel		sa_args.sig = linux_sig;
16149786Smarcel
16251793Smarcel	sa_args.act = nsa;
16351793Smarcel	sa_args.oact = osa;
16451793Smarcel	error = sigaction(p, &sa_args);
16549786Smarcel	if (error)
16651793Smarcel		return (error);
16749786Smarcel
16853954Smarcel	if (linux_osa != NULL)
16953954Smarcel		bsd_to_linux_sigaction(osa, linux_osa);
17051793Smarcel
17151793Smarcel	return (0);
17249786Smarcel}
17349786Smarcel
17468201Sobrien
17568201Sobrien#ifndef __alpha__
1769313Ssosint
17730994Sphklinux_signal(struct proc *p, struct linux_signal_args *args)
17814331Speter{
17951793Smarcel	linux_sigaction_t nsa, osa;
18051793Smarcel	int error;
1819313Ssos
18214331Speter#ifdef DEBUG
18372543Sjlemon	if (ldebug(signal))
18472543Sjlemon		printf(ARGS(signal, "%d, %p"),
18572543Sjlemon		    args->sig, (void *)args->handler);
18614331Speter#endif
18749786Smarcel
18851793Smarcel	nsa.lsa_handler = args->handler;
18951793Smarcel	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
19051793Smarcel	LINUX_SIGEMPTYSET(nsa.lsa_mask);
19149786Smarcel
19251793Smarcel	error = linux_do_sigaction(p, args->sig, &nsa, &osa);
19351793Smarcel	p->p_retval[0] = (int)osa.lsa_handler;
19449786Smarcel
19551793Smarcel	return (error);
19649786Smarcel}
19768201Sobrien#endif	/*!__alpha__*/
19849786Smarcel
19949786Smarcelint
20049786Smarcellinux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args)
20149786Smarcel{
20251793Smarcel	linux_sigaction_t nsa, osa;
20351793Smarcel	int error;
20449786Smarcel
20549786Smarcel#ifdef DEBUG
20672543Sjlemon	if (ldebug(rt_sigaction))
20772543Sjlemon		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
20872543Sjlemon		    (long)args->sig, (void *)args->act,
20972543Sjlemon		    (void *)args->oact, (long)args->sigsetsize);
21049786Smarcel#endif
21149786Smarcel
21251793Smarcel	if (args->sigsetsize != sizeof(linux_sigset_t))
21351793Smarcel		return (EINVAL);
21414331Speter
21551793Smarcel	if (args->act != NULL) {
21651793Smarcel		error = copyin(args->act, &nsa, sizeof(linux_sigaction_t));
21751793Smarcel		if (error)
21851793Smarcel			return (error);
21951793Smarcel	}
22014331Speter
22151793Smarcel	error = linux_do_sigaction(p, args->sig,
22251793Smarcel				   args->act ? &nsa : NULL,
22351793Smarcel				   args->oact ? &osa : NULL);
22414331Speter
22551793Smarcel	if (args->oact != NULL && !error) {
22651793Smarcel		error = copyout(&osa, args->oact, sizeof(linux_sigaction_t));
22751793Smarcel	}
22849786Smarcel
22951793Smarcel	return (error);
23014331Speter}
23114331Speter
23249786Smarcelstatic int
23349786Smarcellinux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new,
23449786Smarcel		     linux_sigset_t *old)
23549786Smarcel{
23670061Sjhb	int error;
23751793Smarcel	sigset_t mask;
23814331Speter
23951793Smarcel	error = 0;
24051793Smarcel	p->p_retval[0] = 0;
24149786Smarcel
24270061Sjhb	PROC_LOCK(p);
24351793Smarcel	if (old != NULL)
24451793Smarcel		bsd_to_linux_sigset(&p->p_sigmask, old);
24549786Smarcel
24651793Smarcel	if (new != NULL) {
24751793Smarcel		linux_to_bsd_sigset(new, &mask);
24849786Smarcel
24951793Smarcel		switch (how) {
25051793Smarcel		case LINUX_SIG_BLOCK:
25151793Smarcel			SIGSETOR(p->p_sigmask, mask);
25251793Smarcel			SIG_CANTMASK(p->p_sigmask);
25351793Smarcel			break;
25451793Smarcel		case LINUX_SIG_UNBLOCK:
25551793Smarcel			SIGSETNAND(p->p_sigmask, mask);
25651793Smarcel			break;
25751793Smarcel		case LINUX_SIG_SETMASK:
25851793Smarcel			p->p_sigmask = mask;
25951793Smarcel			SIG_CANTMASK(p->p_sigmask);
26051793Smarcel			break;
26151793Smarcel		default:
26251793Smarcel			error = EINVAL;
26351793Smarcel			break;
26451793Smarcel		}
26549786Smarcel	}
26670061Sjhb	PROC_UNLOCK(p);
26749786Smarcel
26851793Smarcel	return (error);
26949786Smarcel}
27049786Smarcel
27168201Sobrien#ifndef __alpha__
2729313Ssosint
27330994Sphklinux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args)
2749313Ssos{
27551793Smarcel	linux_osigset_t mask;
27651793Smarcel	linux_sigset_t set, oset;
27751793Smarcel	int error;
2789313Ssos
2799313Ssos#ifdef DEBUG
28072543Sjlemon	if (ldebug(sigprocmask))
28172543Sjlemon		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
2829313Ssos#endif
28314331Speter
28451793Smarcel	if (args->mask != NULL) {
28551793Smarcel		error = copyin(args->mask, &mask, sizeof(linux_osigset_t));
28651793Smarcel		if (error)
28751793Smarcel			return (error);
28851793Smarcel		LINUX_SIGEMPTYSET(set);
28951793Smarcel		set.__bits[0] = mask;
29051793Smarcel	}
29114331Speter
29251793Smarcel	error = linux_do_sigprocmask(p, args->how,
29351793Smarcel				     args->mask ? &set : NULL,
29451793Smarcel				     args->omask ? &oset : NULL);
29549786Smarcel
29651793Smarcel	if (args->omask != NULL && !error) {
29751793Smarcel		mask = oset.__bits[0];
29851793Smarcel		error = copyout(&mask, args->omask, sizeof(linux_osigset_t));
29951793Smarcel	}
30049786Smarcel
30151793Smarcel	return (error);
30249786Smarcel}
30368201Sobrien#endif	/*!__alpha__*/
30449786Smarcel
30549786Smarcelint
30649786Smarcellinux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args)
30749786Smarcel{
30851793Smarcel	linux_sigset_t set, oset;
30951793Smarcel	int error;
31049786Smarcel
31149786Smarcel#ifdef DEBUG
31272543Sjlemon	if (ldebug(rt_sigprocmask))
31372543Sjlemon		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
31472543Sjlemon		    args->how, (void *)args->mask,
31572543Sjlemon		    (void *)args->omask, (long)args->sigsetsize);
31649786Smarcel#endif
31749786Smarcel
31851793Smarcel	if (args->sigsetsize != sizeof(linux_sigset_t))
31951793Smarcel		return EINVAL;
32049786Smarcel
32151793Smarcel	if (args->mask != NULL) {
32251793Smarcel		error = copyin(args->mask, &set, sizeof(linux_sigset_t));
32351793Smarcel		if (error)
32451793Smarcel			return (error);
32551793Smarcel	}
32649786Smarcel
32751793Smarcel	error = linux_do_sigprocmask(p, args->how,
32851793Smarcel				     args->mask ? &set : NULL,
32951793Smarcel				     args->omask ? &oset : NULL);
3309313Ssos
33151793Smarcel	if (args->omask != NULL && !error) {
33251793Smarcel		error = copyout(&oset, args->omask, sizeof(linux_sigset_t));
33351793Smarcel	}
33449786Smarcel
33551793Smarcel	return (error);
3369313Ssos}
3379313Ssos
33868201Sobrien#ifndef __alpha__
3399313Ssosint
34030994Sphklinux_siggetmask(struct proc *p, struct linux_siggetmask_args *args)
3419313Ssos{
34251793Smarcel	linux_sigset_t mask;
34351793Smarcel
3449313Ssos#ifdef DEBUG
34572543Sjlemon	if (ldebug(siggetmask))
34672543Sjlemon		printf(ARGS(siggetmask, ""));
3479313Ssos#endif
34851793Smarcel
34970061Sjhb	PROC_LOCK(p);
35051793Smarcel	bsd_to_linux_sigset(&p->p_sigmask, &mask);
35170061Sjhb	PROC_UNLOCK(p);
35251793Smarcel	p->p_retval[0] = mask.__bits[0];
35351793Smarcel	return (0);
3549313Ssos}
3559313Ssos
3569313Ssosint
35730994Sphklinux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args)
3589313Ssos{
35951793Smarcel	linux_sigset_t lset;
36051793Smarcel	sigset_t bset;
3619313Ssos
3629313Ssos#ifdef DEBUG
36372543Sjlemon	if (ldebug(sigsetmask))
36472543Sjlemon		printf(ARGS(sigsetmask, "%08lx"), (unsigned long)args->mask);
3659313Ssos#endif
36614331Speter
36770061Sjhb	PROC_LOCK(p);
36851793Smarcel	bsd_to_linux_sigset(&p->p_sigmask, &lset);
36951793Smarcel	p->p_retval[0] = lset.__bits[0];
37051793Smarcel	LINUX_SIGEMPTYSET(lset);
37151793Smarcel	lset.__bits[0] = args->mask;
37251793Smarcel	linux_to_bsd_sigset(&lset, &bset);
37351793Smarcel	p->p_sigmask = bset;
37451793Smarcel	SIG_CANTMASK(p->p_sigmask);
37570061Sjhb	PROC_UNLOCK(p);
37651793Smarcel	return (0);
3779313Ssos}
3789313Ssos
3799313Ssosint
38030994Sphklinux_sigpending(struct proc *p, struct linux_sigpending_args *args)
3819313Ssos{
38251793Smarcel	sigset_t bset;
38351793Smarcel	linux_sigset_t lset;
38451793Smarcel	linux_osigset_t mask;
3859313Ssos
3869313Ssos#ifdef DEBUG
38772543Sjlemon	if (ldebug(sigpending))
38872543Sjlemon		printf(ARGS(sigpending, "*"));
3899313Ssos#endif
39051793Smarcel
39170061Sjhb	PROC_LOCK(p);
39251793Smarcel	bset = p->p_siglist;
39351793Smarcel	SIGSETAND(bset, p->p_sigmask);
39451793Smarcel	bsd_to_linux_sigset(&bset, &lset);
39570061Sjhb	PROC_UNLOCK(p);
39651793Smarcel	mask = lset.__bits[0];
39751793Smarcel	return (copyout(&mask, args->mask, sizeof(mask)));
3989313Ssos}
39968201Sobrien#endif	/*!__alpha__*/
4009313Ssos
4019313Ssosint
40230994Sphklinux_kill(struct proc *p, struct linux_kill_args *args)
4039313Ssos{
40451793Smarcel	struct kill_args /* {
40551793Smarcel	    int pid;
40651793Smarcel	    int signum;
40751793Smarcel	} */ tmp;
4089313Ssos
4099313Ssos#ifdef DEBUG
41072543Sjlemon	if (ldebug(kill))
41172543Sjlemon		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
4129313Ssos#endif
41351793Smarcel
41451793Smarcel	/*
41551793Smarcel	 * Allow signal 0 as a means to check for privileges
41651793Smarcel	 */
41751793Smarcel	if (args->signum < 0 || args->signum > LINUX_NSIG)
41851793Smarcel		return EINVAL;
41951793Smarcel
42068201Sobrien#ifndef __alpha__
42151793Smarcel	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
42251793Smarcel		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
42351793Smarcel	else
42468201Sobrien#endif
42551793Smarcel		tmp.signum = args->signum;
42651793Smarcel
42751793Smarcel	tmp.pid = args->pid;
42851793Smarcel	return (kill(p, &tmp));
4299313Ssos}
430