linux_signal.c revision 113859
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
1597748Sschweikh *    derived from this software without 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 113859 2003-04-22 18:23:49Z jhb $
299313Ssos */
309313Ssos
319313Ssos#include <sys/param.h>
329313Ssos#include <sys/systm.h>
3376166Smarkm#include <sys/lock.h>
3476166Smarkm#include <sys/mutex.h>
359313Ssos#include <sys/proc.h>
369313Ssos#include <sys/signalvar.h>
37102814Siedowse#include <sys/syscallsubr.h>
3876166Smarkm#include <sys/sysproto.h>
399313Ssos
4064911Smarcel#include <machine/../linux/linux.h>
4168583Smarcel#include <machine/../linux/linux_proto.h>
4264911Smarcel#include <compat/linux/linux_signal.h>
4364911Smarcel#include <compat/linux/linux_util.h>
449313Ssos
4564911Smarcelvoid
4683221Smarcellinux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
4751793Smarcel{
4851793Smarcel	int b, l;
499313Ssos
5051793Smarcel	SIGEMPTYSET(*bss);
5151793Smarcel	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
5251793Smarcel	bss->__bits[1] = lss->__bits[1];
5351793Smarcel	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
5451793Smarcel		if (LINUX_SIGISMEMBER(*lss, l)) {
5568201Sobrien#ifdef __alpha__
5668201Sobrien			b = _SIG_IDX(l);
5768201Sobrien#else
5851793Smarcel			b = linux_to_bsd_signal[_SIG_IDX(l)];
5968201Sobrien#endif
6051793Smarcel			if (b)
6151793Smarcel				SIGADDSET(*bss, b);
6251793Smarcel		}
6314331Speter	}
649313Ssos}
659313Ssos
6667234Sgallatinvoid
6783221Smarcelbsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
6851793Smarcel{
6951793Smarcel	int b, l;
709313Ssos
7151793Smarcel	LINUX_SIGEMPTYSET(*lss);
7251793Smarcel	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
7351793Smarcel	lss->__bits[1] = bss->__bits[1];
7451793Smarcel	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
7551793Smarcel		if (SIGISMEMBER(*bss, b)) {
7668201Sobrien#if __alpha__
7768201Sobrien			l = _SIG_IDX(b);
7868201Sobrien#else
7951793Smarcel			l = bsd_to_linux_signal[_SIG_IDX(b)];
8068201Sobrien#endif
8151793Smarcel			if (l)
8251793Smarcel				LINUX_SIGADDSET(*lss, l);
8351793Smarcel		}
8414331Speter	}
859313Ssos}
869313Ssos
8714342Speterstatic void
8883221Smarcellinux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
8914331Speter{
9051793Smarcel
9151793Smarcel	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
9251793Smarcel	bsa->sa_handler = lsa->lsa_handler;
9351793Smarcel	bsa->sa_flags = 0;
9451793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
9551793Smarcel		bsa->sa_flags |= SA_NOCLDSTOP;
9651793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
9751793Smarcel		bsa->sa_flags |= SA_NOCLDWAIT;
9851793Smarcel	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
9951793Smarcel		bsa->sa_flags |= SA_SIGINFO;
10051793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
10151793Smarcel		bsa->sa_flags |= SA_ONSTACK;
10251793Smarcel	if (lsa->lsa_flags & LINUX_SA_RESTART)
10351793Smarcel		bsa->sa_flags |= SA_RESTART;
10451793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
10551793Smarcel		bsa->sa_flags |= SA_RESETHAND;
10651793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOMASK)
10751793Smarcel		bsa->sa_flags |= SA_NODEFER;
10814331Speter}
1099313Ssos
11014342Speterstatic void
11183221Smarcelbsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
11214331Speter{
11351793Smarcel
11451793Smarcel	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
11551793Smarcel	lsa->lsa_handler = bsa->sa_handler;
11651793Smarcel	lsa->lsa_restorer = NULL;	/* unsupported */
11751793Smarcel	lsa->lsa_flags = 0;
11851793Smarcel	if (bsa->sa_flags & SA_NOCLDSTOP)
11951793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
12051793Smarcel	if (bsa->sa_flags & SA_NOCLDWAIT)
12151793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
12251793Smarcel	if (bsa->sa_flags & SA_SIGINFO)
12351793Smarcel		lsa->lsa_flags |= LINUX_SA_SIGINFO;
12451793Smarcel	if (bsa->sa_flags & SA_ONSTACK)
12551793Smarcel		lsa->lsa_flags |= LINUX_SA_ONSTACK;
12651793Smarcel	if (bsa->sa_flags & SA_RESTART)
12751793Smarcel		lsa->lsa_flags |= LINUX_SA_RESTART;
12851793Smarcel	if (bsa->sa_flags & SA_RESETHAND)
12951793Smarcel		lsa->lsa_flags |= LINUX_SA_ONESHOT;
13051793Smarcel	if (bsa->sa_flags & SA_NODEFER)
13151793Smarcel		lsa->lsa_flags |= LINUX_SA_NOMASK;
13214331Speter}
13314331Speter
13464911Smarcelint
13583366Sjulianlinux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
13683221Smarcel		   l_sigaction_t *linux_osa)
13749786Smarcel{
138102814Siedowse	struct sigaction act, oact, *nsa, *osa;
139102814Siedowse	int error, sig;
14049786Smarcel
14151793Smarcel	if (linux_sig <= 0 || linux_sig > LINUX_NSIG)
14251793Smarcel		return (EINVAL);
14349786Smarcel
144102814Siedowse	osa = (linux_osa != NULL) ? &oact : NULL;
14551793Smarcel	if (linux_nsa != NULL) {
146102814Siedowse		nsa = &act;
14753954Smarcel		linux_to_bsd_sigaction(linux_nsa, nsa);
148102814Siedowse	} else
14951793Smarcel		nsa = NULL;
15049786Smarcel
15168201Sobrien#ifndef __alpha__
15251793Smarcel	if (linux_sig <= LINUX_SIGTBLSZ)
153102814Siedowse		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
15451793Smarcel	else
15568201Sobrien#endif
156102814Siedowse		sig = linux_sig;
15749786Smarcel
158102814Siedowse	error = kern_sigaction(td, sig, nsa, osa, 0);
15949786Smarcel	if (error)
16051793Smarcel		return (error);
16149786Smarcel
16253954Smarcel	if (linux_osa != NULL)
16353954Smarcel		bsd_to_linux_sigaction(osa, linux_osa);
16451793Smarcel
16551793Smarcel	return (0);
16649786Smarcel}
16749786Smarcel
16868201Sobrien
16968201Sobrien#ifndef __alpha__
1709313Ssosint
17183366Sjulianlinux_signal(struct thread *td, struct linux_signal_args *args)
17214331Speter{
17383221Smarcel	l_sigaction_t nsa, osa;
17451793Smarcel	int error;
1759313Ssos
17614331Speter#ifdef DEBUG
17772543Sjlemon	if (ldebug(signal))
17872543Sjlemon		printf(ARGS(signal, "%d, %p"),
17972543Sjlemon		    args->sig, (void *)args->handler);
18014331Speter#endif
18149786Smarcel
18251793Smarcel	nsa.lsa_handler = args->handler;
18351793Smarcel	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
18451793Smarcel	LINUX_SIGEMPTYSET(nsa.lsa_mask);
18549786Smarcel
18683366Sjulian	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
18783366Sjulian	td->td_retval[0] = (int)osa.lsa_handler;
18849786Smarcel
18951793Smarcel	return (error);
19049786Smarcel}
19168201Sobrien#endif	/*!__alpha__*/
19249786Smarcel
19349786Smarcelint
19483366Sjulianlinux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
19549786Smarcel{
19683221Smarcel	l_sigaction_t nsa, osa;
19751793Smarcel	int error;
19849786Smarcel
19949786Smarcel#ifdef DEBUG
20072543Sjlemon	if (ldebug(rt_sigaction))
20172543Sjlemon		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
20272543Sjlemon		    (long)args->sig, (void *)args->act,
20372543Sjlemon		    (void *)args->oact, (long)args->sigsetsize);
20449786Smarcel#endif
20549786Smarcel
20683221Smarcel	if (args->sigsetsize != sizeof(l_sigset_t))
20751793Smarcel		return (EINVAL);
20814331Speter
20951793Smarcel	if (args->act != NULL) {
21083221Smarcel		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21151793Smarcel		if (error)
21251793Smarcel			return (error);
21351793Smarcel	}
21414331Speter
21583366Sjulian	error = linux_do_sigaction(td, args->sig,
21651793Smarcel				   args->act ? &nsa : NULL,
21751793Smarcel				   args->oact ? &osa : NULL);
21814331Speter
21951793Smarcel	if (args->oact != NULL && !error) {
22083221Smarcel		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22151793Smarcel	}
22249786Smarcel
22351793Smarcel	return (error);
22414331Speter}
22514331Speter
22649786Smarcelstatic int
22783366Sjulianlinux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
22883221Smarcel		     l_sigset_t *old)
22949786Smarcel{
230113859Sjhb	sigset_t omask, nmask;
231113859Sjhb	sigset_t *nmaskp;
23270061Sjhb	int error;
23314331Speter
23483366Sjulian	td->td_retval[0] = 0;
23549786Smarcel
23651793Smarcel	if (new != NULL) {
237113859Sjhb		linux_to_bsd_sigset(new, &nmask);
238113859Sjhb		nmaskp = &nmask;
239113859Sjhb	} else
240113859Sjhb		nmaskp = NULL;
24149786Smarcel
242113859Sjhb	/* Linux sigprocmask flag values are one less than FreeBSD values. */
243113859Sjhb	error = kern_sigprocmask(td, how + 1, nmaskp, &omask, 0);
244113859Sjhb	if (error != 0 && old != NULL)
245113859Sjhb		bsd_to_linux_sigset(&omask, old);
24649786Smarcel
24751793Smarcel	return (error);
24849786Smarcel}
24949786Smarcel
25068201Sobrien#ifndef __alpha__
2519313Ssosint
25283366Sjulianlinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
2539313Ssos{
25483221Smarcel	l_osigset_t mask;
25583221Smarcel	l_sigset_t set, oset;
25651793Smarcel	int error;
2579313Ssos
2589313Ssos#ifdef DEBUG
25972543Sjlemon	if (ldebug(sigprocmask))
26072543Sjlemon		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
2619313Ssos#endif
26214331Speter
26351793Smarcel	if (args->mask != NULL) {
26483221Smarcel		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
26551793Smarcel		if (error)
26651793Smarcel			return (error);
26751793Smarcel		LINUX_SIGEMPTYSET(set);
26851793Smarcel		set.__bits[0] = mask;
26951793Smarcel	}
27014331Speter
27183366Sjulian	error = linux_do_sigprocmask(td, args->how,
27251793Smarcel				     args->mask ? &set : NULL,
27351793Smarcel				     args->omask ? &oset : NULL);
27449786Smarcel
27551793Smarcel	if (args->omask != NULL && !error) {
27651793Smarcel		mask = oset.__bits[0];
27783221Smarcel		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
27851793Smarcel	}
27949786Smarcel
28051793Smarcel	return (error);
28149786Smarcel}
28268201Sobrien#endif	/*!__alpha__*/
28349786Smarcel
28449786Smarcelint
28583366Sjulianlinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
28649786Smarcel{
28783221Smarcel	l_sigset_t set, oset;
28851793Smarcel	int error;
28949786Smarcel
29049786Smarcel#ifdef DEBUG
29172543Sjlemon	if (ldebug(rt_sigprocmask))
29272543Sjlemon		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
29372543Sjlemon		    args->how, (void *)args->mask,
29472543Sjlemon		    (void *)args->omask, (long)args->sigsetsize);
29549786Smarcel#endif
29649786Smarcel
29783221Smarcel	if (args->sigsetsize != sizeof(l_sigset_t))
29851793Smarcel		return EINVAL;
29949786Smarcel
30051793Smarcel	if (args->mask != NULL) {
30183221Smarcel		error = copyin(args->mask, &set, sizeof(l_sigset_t));
30251793Smarcel		if (error)
30351793Smarcel			return (error);
30451793Smarcel	}
30549786Smarcel
30683366Sjulian	error = linux_do_sigprocmask(td, args->how,
30751793Smarcel				     args->mask ? &set : NULL,
30851793Smarcel				     args->omask ? &oset : NULL);
3099313Ssos
31051793Smarcel	if (args->omask != NULL && !error) {
31183221Smarcel		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
31251793Smarcel	}
31349786Smarcel
31451793Smarcel	return (error);
3159313Ssos}
3169313Ssos
31768201Sobrien#ifndef __alpha__
3189313Ssosint
31983366Sjulianlinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
3209313Ssos{
32183366Sjulian	struct proc *p = td->td_proc;
32283221Smarcel	l_sigset_t mask;
32351793Smarcel
3249313Ssos#ifdef DEBUG
32583221Smarcel	if (ldebug(sgetmask))
32683221Smarcel		printf(ARGS(sgetmask, ""));
3279313Ssos#endif
32851793Smarcel
32970061Sjhb	PROC_LOCK(p);
330112888Sjeff	bsd_to_linux_sigset(&td->td_sigmask, &mask);
33170061Sjhb	PROC_UNLOCK(p);
33283366Sjulian	td->td_retval[0] = mask.__bits[0];
33351793Smarcel	return (0);
3349313Ssos}
3359313Ssos
3369313Ssosint
33783366Sjulianlinux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
3389313Ssos{
33983366Sjulian	struct proc *p = td->td_proc;
34083221Smarcel	l_sigset_t lset;
34151793Smarcel	sigset_t bset;
3429313Ssos
3439313Ssos#ifdef DEBUG
34483221Smarcel	if (ldebug(ssetmask))
34583221Smarcel		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
3469313Ssos#endif
34714331Speter
34870061Sjhb	PROC_LOCK(p);
349112888Sjeff	bsd_to_linux_sigset(&td->td_sigmask, &lset);
35083366Sjulian	td->td_retval[0] = lset.__bits[0];
35151793Smarcel	LINUX_SIGEMPTYSET(lset);
35251793Smarcel	lset.__bits[0] = args->mask;
35351793Smarcel	linux_to_bsd_sigset(&lset, &bset);
354112888Sjeff	td->td_sigmask = bset;
355112888Sjeff	SIG_CANTMASK(td->td_sigmask);
356112888Sjeff	signotify(td);
35770061Sjhb	PROC_UNLOCK(p);
35851793Smarcel	return (0);
3599313Ssos}
3609313Ssos
361110980Stjr/*
362110980Stjr * MPSAFE
363110980Stjr */
3649313Ssosint
36583366Sjulianlinux_sigpending(struct thread *td, struct linux_sigpending_args *args)
3669313Ssos{
36783366Sjulian	struct proc *p = td->td_proc;
36851793Smarcel	sigset_t bset;
36983221Smarcel	l_sigset_t lset;
37083221Smarcel	l_osigset_t mask;
3719313Ssos
3729313Ssos#ifdef DEBUG
37372543Sjlemon	if (ldebug(sigpending))
37472543Sjlemon		printf(ARGS(sigpending, "*"));
3759313Ssos#endif
37651793Smarcel
37770061Sjhb	PROC_LOCK(p);
378104306Sjmallett	bset = p->p_siglist;
379112888Sjeff	SIGSETOR(bset, td->td_siglist);
380112888Sjeff	SIGSETAND(bset, td->td_sigmask);
381113615Sjhb	PROC_UNLOCK(p);
38251793Smarcel	bsd_to_linux_sigset(&bset, &lset);
38351793Smarcel	mask = lset.__bits[0];
38451793Smarcel	return (copyout(&mask, args->mask, sizeof(mask)));
3859313Ssos}
38668201Sobrien#endif	/*!__alpha__*/
3879313Ssos
3889313Ssosint
38983366Sjulianlinux_kill(struct thread *td, struct linux_kill_args *args)
3909313Ssos{
39151793Smarcel	struct kill_args /* {
39251793Smarcel	    int pid;
39351793Smarcel	    int signum;
39451793Smarcel	} */ tmp;
3959313Ssos
3969313Ssos#ifdef DEBUG
39772543Sjlemon	if (ldebug(kill))
39872543Sjlemon		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
3999313Ssos#endif
40051793Smarcel
40151793Smarcel	/*
40251793Smarcel	 * Allow signal 0 as a means to check for privileges
40351793Smarcel	 */
40451793Smarcel	if (args->signum < 0 || args->signum > LINUX_NSIG)
40551793Smarcel		return EINVAL;
40651793Smarcel
40768201Sobrien#ifndef __alpha__
40851793Smarcel	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
40951793Smarcel		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
41051793Smarcel	else
41168201Sobrien#endif
41251793Smarcel		tmp.signum = args->signum;
41351793Smarcel
41451793Smarcel	tmp.pid = args->pid;
41583366Sjulian	return (kill(td, &tmp));
4169313Ssos}
417