linux_signal.c revision 104306
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 104306 2002-10-01 17:15:53Z jmallett $
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{
23070061Sjhb	int error;
23151793Smarcel	sigset_t mask;
23283366Sjulian	struct proc *p = td->td_proc;
23314331Speter
23451793Smarcel	error = 0;
23583366Sjulian	td->td_retval[0] = 0;
23649786Smarcel
23770061Sjhb	PROC_LOCK(p);
23851793Smarcel	if (old != NULL)
23951793Smarcel		bsd_to_linux_sigset(&p->p_sigmask, old);
24049786Smarcel
24151793Smarcel	if (new != NULL) {
24251793Smarcel		linux_to_bsd_sigset(new, &mask);
24349786Smarcel
24451793Smarcel		switch (how) {
24551793Smarcel		case LINUX_SIG_BLOCK:
24651793Smarcel			SIGSETOR(p->p_sigmask, mask);
24751793Smarcel			SIG_CANTMASK(p->p_sigmask);
24851793Smarcel			break;
24951793Smarcel		case LINUX_SIG_UNBLOCK:
25051793Smarcel			SIGSETNAND(p->p_sigmask, mask);
25193793Sbde			signotify(p);
25251793Smarcel			break;
25351793Smarcel		case LINUX_SIG_SETMASK:
25451793Smarcel			p->p_sigmask = mask;
25551793Smarcel			SIG_CANTMASK(p->p_sigmask);
25693793Sbde			signotify(p);
25751793Smarcel			break;
25851793Smarcel		default:
25951793Smarcel			error = EINVAL;
26051793Smarcel			break;
26151793Smarcel		}
26249786Smarcel	}
26370061Sjhb	PROC_UNLOCK(p);
26449786Smarcel
26551793Smarcel	return (error);
26649786Smarcel}
26749786Smarcel
26868201Sobrien#ifndef __alpha__
2699313Ssosint
27083366Sjulianlinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
2719313Ssos{
27283221Smarcel	l_osigset_t mask;
27383221Smarcel	l_sigset_t set, oset;
27451793Smarcel	int error;
2759313Ssos
2769313Ssos#ifdef DEBUG
27772543Sjlemon	if (ldebug(sigprocmask))
27872543Sjlemon		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
2799313Ssos#endif
28014331Speter
28151793Smarcel	if (args->mask != NULL) {
28283221Smarcel		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
28351793Smarcel		if (error)
28451793Smarcel			return (error);
28551793Smarcel		LINUX_SIGEMPTYSET(set);
28651793Smarcel		set.__bits[0] = mask;
28751793Smarcel	}
28814331Speter
28983366Sjulian	error = linux_do_sigprocmask(td, args->how,
29051793Smarcel				     args->mask ? &set : NULL,
29151793Smarcel				     args->omask ? &oset : NULL);
29249786Smarcel
29351793Smarcel	if (args->omask != NULL && !error) {
29451793Smarcel		mask = oset.__bits[0];
29583221Smarcel		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
29651793Smarcel	}
29749786Smarcel
29851793Smarcel	return (error);
29949786Smarcel}
30068201Sobrien#endif	/*!__alpha__*/
30149786Smarcel
30249786Smarcelint
30383366Sjulianlinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
30449786Smarcel{
30583221Smarcel	l_sigset_t set, oset;
30651793Smarcel	int error;
30749786Smarcel
30849786Smarcel#ifdef DEBUG
30972543Sjlemon	if (ldebug(rt_sigprocmask))
31072543Sjlemon		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
31172543Sjlemon		    args->how, (void *)args->mask,
31272543Sjlemon		    (void *)args->omask, (long)args->sigsetsize);
31349786Smarcel#endif
31449786Smarcel
31583221Smarcel	if (args->sigsetsize != sizeof(l_sigset_t))
31651793Smarcel		return EINVAL;
31749786Smarcel
31851793Smarcel	if (args->mask != NULL) {
31983221Smarcel		error = copyin(args->mask, &set, sizeof(l_sigset_t));
32051793Smarcel		if (error)
32151793Smarcel			return (error);
32251793Smarcel	}
32349786Smarcel
32483366Sjulian	error = linux_do_sigprocmask(td, args->how,
32551793Smarcel				     args->mask ? &set : NULL,
32651793Smarcel				     args->omask ? &oset : NULL);
3279313Ssos
32851793Smarcel	if (args->omask != NULL && !error) {
32983221Smarcel		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
33051793Smarcel	}
33149786Smarcel
33251793Smarcel	return (error);
3339313Ssos}
3349313Ssos
33568201Sobrien#ifndef __alpha__
3369313Ssosint
33783366Sjulianlinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
3389313Ssos{
33983366Sjulian	struct proc *p = td->td_proc;
34083221Smarcel	l_sigset_t mask;
34151793Smarcel
3429313Ssos#ifdef DEBUG
34383221Smarcel	if (ldebug(sgetmask))
34483221Smarcel		printf(ARGS(sgetmask, ""));
3459313Ssos#endif
34651793Smarcel
34770061Sjhb	PROC_LOCK(p);
34851793Smarcel	bsd_to_linux_sigset(&p->p_sigmask, &mask);
34970061Sjhb	PROC_UNLOCK(p);
35083366Sjulian	td->td_retval[0] = mask.__bits[0];
35151793Smarcel	return (0);
3529313Ssos}
3539313Ssos
3549313Ssosint
35583366Sjulianlinux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
3569313Ssos{
35783366Sjulian	struct proc *p = td->td_proc;
35883221Smarcel	l_sigset_t lset;
35951793Smarcel	sigset_t bset;
3609313Ssos
3619313Ssos#ifdef DEBUG
36283221Smarcel	if (ldebug(ssetmask))
36383221Smarcel		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
3649313Ssos#endif
36514331Speter
36670061Sjhb	PROC_LOCK(p);
36751793Smarcel	bsd_to_linux_sigset(&p->p_sigmask, &lset);
36883366Sjulian	td->td_retval[0] = lset.__bits[0];
36951793Smarcel	LINUX_SIGEMPTYSET(lset);
37051793Smarcel	lset.__bits[0] = args->mask;
37151793Smarcel	linux_to_bsd_sigset(&lset, &bset);
37251793Smarcel	p->p_sigmask = bset;
37351793Smarcel	SIG_CANTMASK(p->p_sigmask);
37493793Sbde	signotify(p);
37570061Sjhb	PROC_UNLOCK(p);
37651793Smarcel	return (0);
3779313Ssos}
3789313Ssos
3799313Ssosint
38083366Sjulianlinux_sigpending(struct thread *td, struct linux_sigpending_args *args)
3819313Ssos{
38283366Sjulian	struct proc *p = td->td_proc;
38351793Smarcel	sigset_t bset;
38483221Smarcel	l_sigset_t lset;
38583221Smarcel	l_osigset_t mask;
3869313Ssos
3879313Ssos#ifdef DEBUG
38872543Sjlemon	if (ldebug(sigpending))
38972543Sjlemon		printf(ARGS(sigpending, "*"));
3909313Ssos#endif
39151793Smarcel
39270061Sjhb	PROC_LOCK(p);
393104306Sjmallett	bset = p->p_siglist;
39451793Smarcel	SIGSETAND(bset, p->p_sigmask);
39551793Smarcel	bsd_to_linux_sigset(&bset, &lset);
39670061Sjhb	PROC_UNLOCK(p);
39751793Smarcel	mask = lset.__bits[0];
39851793Smarcel	return (copyout(&mask, args->mask, sizeof(mask)));
3999313Ssos}
40068201Sobrien#endif	/*!__alpha__*/
4019313Ssos
4029313Ssosint
40383366Sjulianlinux_kill(struct thread *td, struct linux_kill_args *args)
4049313Ssos{
40551793Smarcel	struct kill_args /* {
40651793Smarcel	    int pid;
40751793Smarcel	    int signum;
40851793Smarcel	} */ tmp;
4099313Ssos
4109313Ssos#ifdef DEBUG
41172543Sjlemon	if (ldebug(kill))
41272543Sjlemon		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
4139313Ssos#endif
41451793Smarcel
41551793Smarcel	/*
41651793Smarcel	 * Allow signal 0 as a means to check for privileges
41751793Smarcel	 */
41851793Smarcel	if (args->signum < 0 || args->signum > LINUX_NSIG)
41951793Smarcel		return EINVAL;
42051793Smarcel
42168201Sobrien#ifndef __alpha__
42251793Smarcel	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
42351793Smarcel		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
42451793Smarcel	else
42568201Sobrien#endif
42651793Smarcel		tmp.signum = args->signum;
42751793Smarcel
42851793Smarcel	tmp.pid = args->pid;
42983366Sjulian	return (kill(td, &tmp));
4309313Ssos}
431