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 */
289313Ssos
29116173Sobrien#include <sys/cdefs.h>
30141829Snjl__FBSDID("$FreeBSD$");
31116173Sobrien
329313Ssos#include <sys/param.h>
339313Ssos#include <sys/systm.h>
3476166Smarkm#include <sys/lock.h>
3576166Smarkm#include <sys/mutex.h>
36161461Snetchild#include <sys/sx.h>
379313Ssos#include <sys/proc.h>
389313Ssos#include <sys/signalvar.h>
39102814Siedowse#include <sys/syscallsubr.h>
4076166Smarkm#include <sys/sysproto.h>
419313Ssos
42184058Skib#include <security/audit/audit.h>
43184058Skib
44156874Sru#include "opt_compat.h"
45156874Sru
46140214Sobrien#ifdef COMPAT_LINUX32
47140214Sobrien#include <machine/../linux32/linux.h>
48140214Sobrien#include <machine/../linux32/linux32_proto.h>
49140214Sobrien#else
5064911Smarcel#include <machine/../linux/linux.h>
5168583Smarcel#include <machine/../linux/linux_proto.h>
52133816Stjr#endif
5364911Smarcel#include <compat/linux/linux_signal.h>
5464911Smarcel#include <compat/linux/linux_util.h>
55161310Snetchild#include <compat/linux/linux_emul.h>
569313Ssos
5764911Smarcelvoid
5883221Smarcellinux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
5951793Smarcel{
6051793Smarcel	int b, l;
619313Ssos
6251793Smarcel	SIGEMPTYSET(*bss);
6351793Smarcel	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
6451793Smarcel	bss->__bits[1] = lss->__bits[1];
6551793Smarcel	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
6651793Smarcel		if (LINUX_SIGISMEMBER(*lss, l)) {
6751793Smarcel			b = linux_to_bsd_signal[_SIG_IDX(l)];
6851793Smarcel			if (b)
6951793Smarcel				SIGADDSET(*bss, b);
7051793Smarcel		}
7114331Speter	}
729313Ssos}
739313Ssos
7467234Sgallatinvoid
7583221Smarcelbsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
7651793Smarcel{
7751793Smarcel	int b, l;
789313Ssos
7951793Smarcel	LINUX_SIGEMPTYSET(*lss);
8051793Smarcel	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
8151793Smarcel	lss->__bits[1] = bss->__bits[1];
8251793Smarcel	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
8351793Smarcel		if (SIGISMEMBER(*bss, b)) {
8451793Smarcel			l = bsd_to_linux_signal[_SIG_IDX(b)];
8551793Smarcel			if (l)
8651793Smarcel				LINUX_SIGADDSET(*lss, l);
8751793Smarcel		}
8814331Speter	}
899313Ssos}
909313Ssos
9114342Speterstatic void
9283221Smarcellinux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
9314331Speter{
9451793Smarcel
9551793Smarcel	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
96133816Stjr	bsa->sa_handler = PTRIN(lsa->lsa_handler);
9751793Smarcel	bsa->sa_flags = 0;
9851793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
9951793Smarcel		bsa->sa_flags |= SA_NOCLDSTOP;
10051793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
10151793Smarcel		bsa->sa_flags |= SA_NOCLDWAIT;
10251793Smarcel	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
10351793Smarcel		bsa->sa_flags |= SA_SIGINFO;
10451793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
10551793Smarcel		bsa->sa_flags |= SA_ONSTACK;
10651793Smarcel	if (lsa->lsa_flags & LINUX_SA_RESTART)
10751793Smarcel		bsa->sa_flags |= SA_RESTART;
10851793Smarcel	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
10951793Smarcel		bsa->sa_flags |= SA_RESETHAND;
11051793Smarcel	if (lsa->lsa_flags & LINUX_SA_NOMASK)
11151793Smarcel		bsa->sa_flags |= SA_NODEFER;
11214331Speter}
1139313Ssos
11414342Speterstatic void
11583221Smarcelbsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
11614331Speter{
11751793Smarcel
11851793Smarcel	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
119140214Sobrien#ifdef COMPAT_LINUX32
120133816Stjr	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
121133816Stjr#else
12251793Smarcel	lsa->lsa_handler = bsa->sa_handler;
123133816Stjr#endif
124133816Stjr	lsa->lsa_restorer = 0;		/* unsupported */
12551793Smarcel	lsa->lsa_flags = 0;
12651793Smarcel	if (bsa->sa_flags & SA_NOCLDSTOP)
12751793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
12851793Smarcel	if (bsa->sa_flags & SA_NOCLDWAIT)
12951793Smarcel		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
13051793Smarcel	if (bsa->sa_flags & SA_SIGINFO)
13151793Smarcel		lsa->lsa_flags |= LINUX_SA_SIGINFO;
13251793Smarcel	if (bsa->sa_flags & SA_ONSTACK)
13351793Smarcel		lsa->lsa_flags |= LINUX_SA_ONSTACK;
13451793Smarcel	if (bsa->sa_flags & SA_RESTART)
13551793Smarcel		lsa->lsa_flags |= LINUX_SA_RESTART;
13651793Smarcel	if (bsa->sa_flags & SA_RESETHAND)
13751793Smarcel		lsa->lsa_flags |= LINUX_SA_ONESHOT;
13851793Smarcel	if (bsa->sa_flags & SA_NODEFER)
13951793Smarcel		lsa->lsa_flags |= LINUX_SA_NOMASK;
14014331Speter}
14114331Speter
14264911Smarcelint
14383366Sjulianlinux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
14483221Smarcel		   l_sigaction_t *linux_osa)
14549786Smarcel{
146102814Siedowse	struct sigaction act, oact, *nsa, *osa;
147102814Siedowse	int error, sig;
14849786Smarcel
149163369Snetchild	if (!LINUX_SIG_VALID(linux_sig))
15051793Smarcel		return (EINVAL);
15149786Smarcel
152102814Siedowse	osa = (linux_osa != NULL) ? &oact : NULL;
15351793Smarcel	if (linux_nsa != NULL) {
154102814Siedowse		nsa = &act;
15553954Smarcel		linux_to_bsd_sigaction(linux_nsa, nsa);
156102814Siedowse	} else
15751793Smarcel		nsa = NULL;
15849786Smarcel
15951793Smarcel	if (linux_sig <= LINUX_SIGTBLSZ)
160102814Siedowse		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
16151793Smarcel	else
162102814Siedowse		sig = linux_sig;
16349786Smarcel
164102814Siedowse	error = kern_sigaction(td, sig, nsa, osa, 0);
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
1759313Ssosint
17683366Sjulianlinux_signal(struct thread *td, struct linux_signal_args *args)
17714331Speter{
17883221Smarcel	l_sigaction_t nsa, osa;
17951793Smarcel	int error;
1809313Ssos
18114331Speter#ifdef DEBUG
18272543Sjlemon	if (ldebug(signal))
18372543Sjlemon		printf(ARGS(signal, "%d, %p"),
184133850Sobrien		    args->sig, (void *)(uintptr_t)args->handler);
18514331Speter#endif
18649786Smarcel
18751793Smarcel	nsa.lsa_handler = args->handler;
18851793Smarcel	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
18951793Smarcel	LINUX_SIGEMPTYSET(nsa.lsa_mask);
19049786Smarcel
19183366Sjulian	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
192133816Stjr	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
19349786Smarcel
19451793Smarcel	return (error);
19549786Smarcel}
19649786Smarcel
19749786Smarcelint
19883366Sjulianlinux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
19949786Smarcel{
20083221Smarcel	l_sigaction_t nsa, osa;
20151793Smarcel	int error;
20249786Smarcel
20349786Smarcel#ifdef DEBUG
20472543Sjlemon	if (ldebug(rt_sigaction))
20572543Sjlemon		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
20672543Sjlemon		    (long)args->sig, (void *)args->act,
20772543Sjlemon		    (void *)args->oact, (long)args->sigsetsize);
20849786Smarcel#endif
20949786Smarcel
21083221Smarcel	if (args->sigsetsize != sizeof(l_sigset_t))
21151793Smarcel		return (EINVAL);
21214331Speter
21351793Smarcel	if (args->act != NULL) {
21483221Smarcel		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21551793Smarcel		if (error)
21651793Smarcel			return (error);
21751793Smarcel	}
21814331Speter
21983366Sjulian	error = linux_do_sigaction(td, args->sig,
22051793Smarcel				   args->act ? &nsa : NULL,
22151793Smarcel				   args->oact ? &osa : NULL);
22214331Speter
22351793Smarcel	if (args->oact != NULL && !error) {
22483221Smarcel		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22551793Smarcel	}
22649786Smarcel
22751793Smarcel	return (error);
22814331Speter}
22914331Speter
23049786Smarcelstatic int
23183366Sjulianlinux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
23283221Smarcel		     l_sigset_t *old)
23349786Smarcel{
234113859Sjhb	sigset_t omask, nmask;
235113859Sjhb	sigset_t *nmaskp;
23670061Sjhb	int error;
23714331Speter
23883366Sjulian	td->td_retval[0] = 0;
23949786Smarcel
240114023Sjhb	switch (how) {
241114023Sjhb	case LINUX_SIG_BLOCK:
242114023Sjhb		how = SIG_BLOCK;
243114023Sjhb		break;
244114023Sjhb	case LINUX_SIG_UNBLOCK:
245114023Sjhb		how = SIG_UNBLOCK;
246114023Sjhb		break;
247114023Sjhb	case LINUX_SIG_SETMASK:
248114023Sjhb		how = SIG_SETMASK;
249114023Sjhb		break;
250114023Sjhb	default:
251114023Sjhb		return (EINVAL);
252114023Sjhb	}
25351793Smarcel	if (new != NULL) {
254113859Sjhb		linux_to_bsd_sigset(new, &nmask);
255113859Sjhb		nmaskp = &nmask;
256113859Sjhb	} else
257113859Sjhb		nmaskp = NULL;
258114023Sjhb	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
259114174Sjhb	if (error == 0 && old != NULL)
260113859Sjhb		bsd_to_linux_sigset(&omask, old);
26149786Smarcel
26251793Smarcel	return (error);
26349786Smarcel}
26449786Smarcel
2659313Ssosint
26683366Sjulianlinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
2679313Ssos{
26883221Smarcel	l_osigset_t mask;
26983221Smarcel	l_sigset_t set, oset;
27051793Smarcel	int error;
2719313Ssos
2729313Ssos#ifdef DEBUG
27372543Sjlemon	if (ldebug(sigprocmask))
27472543Sjlemon		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
2759313Ssos#endif
27614331Speter
27751793Smarcel	if (args->mask != NULL) {
27883221Smarcel		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
27951793Smarcel		if (error)
28051793Smarcel			return (error);
28151793Smarcel		LINUX_SIGEMPTYSET(set);
28251793Smarcel		set.__bits[0] = mask;
28351793Smarcel	}
28414331Speter
28583366Sjulian	error = linux_do_sigprocmask(td, args->how,
28651793Smarcel				     args->mask ? &set : NULL,
28751793Smarcel				     args->omask ? &oset : NULL);
28849786Smarcel
28951793Smarcel	if (args->omask != NULL && !error) {
29051793Smarcel		mask = oset.__bits[0];
29183221Smarcel		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
29251793Smarcel	}
29349786Smarcel
29451793Smarcel	return (error);
29549786Smarcel}
29649786Smarcel
29749786Smarcelint
29883366Sjulianlinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
29949786Smarcel{
30083221Smarcel	l_sigset_t set, oset;
30151793Smarcel	int error;
30249786Smarcel
30349786Smarcel#ifdef DEBUG
30472543Sjlemon	if (ldebug(rt_sigprocmask))
30572543Sjlemon		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
30672543Sjlemon		    args->how, (void *)args->mask,
30772543Sjlemon		    (void *)args->omask, (long)args->sigsetsize);
30849786Smarcel#endif
30949786Smarcel
31083221Smarcel	if (args->sigsetsize != sizeof(l_sigset_t))
31151793Smarcel		return EINVAL;
31249786Smarcel
31351793Smarcel	if (args->mask != NULL) {
31483221Smarcel		error = copyin(args->mask, &set, sizeof(l_sigset_t));
31551793Smarcel		if (error)
31651793Smarcel			return (error);
31751793Smarcel	}
31849786Smarcel
31983366Sjulian	error = linux_do_sigprocmask(td, args->how,
32051793Smarcel				     args->mask ? &set : NULL,
32151793Smarcel				     args->omask ? &oset : NULL);
3229313Ssos
32351793Smarcel	if (args->omask != NULL && !error) {
32483221Smarcel		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
32551793Smarcel	}
32649786Smarcel
32751793Smarcel	return (error);
3289313Ssos}
3299313Ssos
3309313Ssosint
33183366Sjulianlinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
3329313Ssos{
33383366Sjulian	struct proc *p = td->td_proc;
33483221Smarcel	l_sigset_t mask;
33551793Smarcel
3369313Ssos#ifdef DEBUG
33783221Smarcel	if (ldebug(sgetmask))
33883221Smarcel		printf(ARGS(sgetmask, ""));
3399313Ssos#endif
34051793Smarcel
34170061Sjhb	PROC_LOCK(p);
342112888Sjeff	bsd_to_linux_sigset(&td->td_sigmask, &mask);
34370061Sjhb	PROC_UNLOCK(p);
34483366Sjulian	td->td_retval[0] = mask.__bits[0];
34551793Smarcel	return (0);
3469313Ssos}
3479313Ssos
3489313Ssosint
34983366Sjulianlinux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
3509313Ssos{
35183366Sjulian	struct proc *p = td->td_proc;
35283221Smarcel	l_sigset_t lset;
35351793Smarcel	sigset_t bset;
3549313Ssos
3559313Ssos#ifdef DEBUG
35683221Smarcel	if (ldebug(ssetmask))
35783221Smarcel		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
3589313Ssos#endif
35914331Speter
36070061Sjhb	PROC_LOCK(p);
361112888Sjeff	bsd_to_linux_sigset(&td->td_sigmask, &lset);
36283366Sjulian	td->td_retval[0] = lset.__bits[0];
36351793Smarcel	LINUX_SIGEMPTYSET(lset);
36451793Smarcel	lset.__bits[0] = args->mask;
36551793Smarcel	linux_to_bsd_sigset(&lset, &bset);
366112888Sjeff	td->td_sigmask = bset;
367112888Sjeff	SIG_CANTMASK(td->td_sigmask);
368112888Sjeff	signotify(td);
36970061Sjhb	PROC_UNLOCK(p);
37051793Smarcel	return (0);
3719313Ssos}
3729313Ssos
373110980Stjr/*
374110980Stjr * MPSAFE
375110980Stjr */
3769313Ssosint
37783366Sjulianlinux_sigpending(struct thread *td, struct linux_sigpending_args *args)
3789313Ssos{
37983366Sjulian	struct proc *p = td->td_proc;
38051793Smarcel	sigset_t bset;
38183221Smarcel	l_sigset_t lset;
38283221Smarcel	l_osigset_t mask;
3839313Ssos
3849313Ssos#ifdef DEBUG
38572543Sjlemon	if (ldebug(sigpending))
38672543Sjlemon		printf(ARGS(sigpending, "*"));
3879313Ssos#endif
38851793Smarcel
38970061Sjhb	PROC_LOCK(p);
390104306Sjmallett	bset = p->p_siglist;
391112888Sjeff	SIGSETOR(bset, td->td_siglist);
392112888Sjeff	SIGSETAND(bset, td->td_sigmask);
393113615Sjhb	PROC_UNLOCK(p);
39451793Smarcel	bsd_to_linux_sigset(&bset, &lset);
39551793Smarcel	mask = lset.__bits[0];
39651793Smarcel	return (copyout(&mask, args->mask, sizeof(mask)));
3979313Ssos}
398158406Snetchild
399158406Snetchild/*
400158406Snetchild * MPSAFE
401158406Snetchild */
402158406Snetchildint
403158406Snetchildlinux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
404158406Snetchild{
405158406Snetchild	struct proc *p = td->td_proc;
406158406Snetchild	sigset_t bset;
407158406Snetchild	l_sigset_t lset;
408158406Snetchild
409158406Snetchild	if (args->sigsetsize > sizeof(lset))
410158406Snetchild		return EINVAL;
411158406Snetchild		/* NOT REACHED */
412158406Snetchild
413158406Snetchild#ifdef DEBUG
414158406Snetchild	if (ldebug(rt_sigpending))
415158406Snetchild		printf(ARGS(rt_sigpending, "*"));
416158406Snetchild#endif
417158406Snetchild
418158406Snetchild	PROC_LOCK(p);
419158406Snetchild	bset = p->p_siglist;
420158406Snetchild	SIGSETOR(bset, td->td_siglist);
421158406Snetchild	SIGSETAND(bset, td->td_sigmask);
422158406Snetchild	PROC_UNLOCK(p);
423158406Snetchild	bsd_to_linux_sigset(&bset, &lset);
424158406Snetchild	return (copyout(&lset, args->set, args->sigsetsize));
425158406Snetchild}
4269313Ssos
427165689Snetchild/*
428165689Snetchild * MPSAFE
429165689Snetchild */
4309313Ssosint
431165689Snetchildlinux_rt_sigtimedwait(struct thread *td,
432165689Snetchild	struct linux_rt_sigtimedwait_args *args)
433165689Snetchild{
434218719Sdchagin	int error, sig;
435165689Snetchild	l_timeval ltv;
436165689Snetchild	struct timeval tv;
437165689Snetchild	struct timespec ts, *tsa;
438165689Snetchild	l_sigset_t lset;
439165689Snetchild	sigset_t bset;
440165689Snetchild	l_siginfo_t linfo;
441165689Snetchild	ksiginfo_t info;
442165689Snetchild
443165689Snetchild#ifdef DEBUG
444165689Snetchild	if (ldebug(rt_sigtimedwait))
445165689Snetchild		printf(ARGS(rt_sigtimedwait, "*"));
446165689Snetchild#endif
447165689Snetchild	if (args->sigsetsize != sizeof(l_sigset_t))
448165689Snetchild		return (EINVAL);
449165689Snetchild
450165689Snetchild	if ((error = copyin(args->mask, &lset, sizeof(lset))))
451165689Snetchild		return (error);
452165689Snetchild	linux_to_bsd_sigset(&lset, &bset);
453165689Snetchild
454165689Snetchild	tsa = NULL;
455165689Snetchild	if (args->timeout) {
456165689Snetchild		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
457165689Snetchild			return (error);
458165689Snetchild#ifdef DEBUG
459165689Snetchild		if (ldebug(rt_sigtimedwait))
460218718Sdchagin			printf(LMSG("linux_rt_sigtimedwait: "
461218718Sdchagin			    "incoming timeout (%d/%d)\n"),
462218718Sdchagin			    ltv.tv_sec, ltv.tv_usec);
463165689Snetchild#endif
464165689Snetchild		tv.tv_sec = (long)ltv.tv_sec;
465165689Snetchild		tv.tv_usec = (suseconds_t)ltv.tv_usec;
466165689Snetchild		if (itimerfix(&tv)) {
467165689Snetchild			/*
468165689Snetchild			 * The timeout was invalid. Convert it to something
469165689Snetchild			 * valid that will act as it does under Linux.
470165689Snetchild			 */
471165689Snetchild			tv.tv_sec += tv.tv_usec / 1000000;
472165689Snetchild			tv.tv_usec %= 1000000;
473165689Snetchild			if (tv.tv_usec < 0) {
474165689Snetchild				tv.tv_sec -= 1;
475165689Snetchild				tv.tv_usec += 1000000;
476165689Snetchild			}
477165689Snetchild			if (tv.tv_sec < 0)
478165689Snetchild				timevalclear(&tv);
479165689Snetchild#ifdef DEBUG
480165689Snetchild			if (ldebug(rt_sigtimedwait))
481218718Sdchagin				printf(LMSG("linux_rt_sigtimedwait: "
482218718Sdchagin				    "converted timeout (%jd/%ld)\n"),
483218718Sdchagin				    (intmax_t)tv.tv_sec, tv.tv_usec);
484165689Snetchild#endif
485165689Snetchild		}
486165689Snetchild		TIMEVAL_TO_TIMESPEC(&tv, &ts);
487165689Snetchild		tsa = &ts;
488165689Snetchild	}
489165689Snetchild	error = kern_sigtimedwait(td, bset, &info, tsa);
490165689Snetchild#ifdef DEBUG
491165689Snetchild	if (ldebug(rt_sigtimedwait))
492218718Sdchagin		printf(LMSG("linux_rt_sigtimedwait: "
493218718Sdchagin		    "sigtimedwait returning (%d)\n"), error);
494165689Snetchild#endif
495165689Snetchild	if (error)
496165689Snetchild		return (error);
497165689Snetchild
498218719Sdchagin	sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
499218719Sdchagin
500165689Snetchild	if (args->ptr) {
501165689Snetchild		memset(&linfo, 0, sizeof(linfo));
502218719Sdchagin		ksiginfo_to_lsiginfo(&info, &linfo, sig);
503165689Snetchild		error = copyout(&linfo, args->ptr, sizeof(linfo));
504165689Snetchild	}
505218719Sdchagin	if (error == 0)
506218719Sdchagin		td->td_retval[0] = sig;
507165689Snetchild
508165689Snetchild	return (error);
509165689Snetchild}
510165689Snetchild
511165689Snetchildint
51283366Sjulianlinux_kill(struct thread *td, struct linux_kill_args *args)
5139313Ssos{
51451793Smarcel	struct kill_args /* {
51551793Smarcel	    int pid;
51651793Smarcel	    int signum;
51751793Smarcel	} */ tmp;
5189313Ssos
5199313Ssos#ifdef DEBUG
52072543Sjlemon	if (ldebug(kill))
52172543Sjlemon		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
5229313Ssos#endif
52351793Smarcel
52451793Smarcel	/*
52551793Smarcel	 * Allow signal 0 as a means to check for privileges
52651793Smarcel	 */
527163381Snetchild	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
528217743Sdchagin		return (EINVAL);
52951793Smarcel
53051793Smarcel	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
53151793Smarcel		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
53251793Smarcel	else
53351793Smarcel		tmp.signum = args->signum;
53451793Smarcel
53551793Smarcel	tmp.pid = args->pid;
536225617Skmacy	return (sys_kill(td, &tmp));
5379313Ssos}
538161310Snetchild
539184058Skibstatic int
540184058Skiblinux_do_tkill(struct thread *td, l_int tgid, l_int pid, l_int signum)
541161310Snetchild{
542184058Skib	struct proc *proc = td->td_proc;
543184058Skib	struct linux_emuldata *em;
544161310Snetchild	struct proc *p;
545184058Skib	ksiginfo_t ksi;
546184058Skib	int error;
547161310Snetchild
548195104Srwatson	AUDIT_ARG_SIGNUM(signum);
549195104Srwatson	AUDIT_ARG_PID(pid);
550161310Snetchild
551184058Skib	/*
552184058Skib	 * Allow signal 0 as a means to check for privileges
553184058Skib	 */
554184058Skib	if (!LINUX_SIG_VALID(signum) && signum != 0)
555184058Skib		return (EINVAL);
556161310Snetchild
557184058Skib	if (signum > 0 && signum <= LINUX_SIGTBLSZ)
558184058Skib		signum = linux_to_bsd_signal[_SIG_IDX(signum)];
559161310Snetchild
560184058Skib	if ((p = pfind(pid)) == NULL) {
561184058Skib		if ((p = zpfind(pid)) == NULL)
562184058Skib			return (ESRCH);
563184058Skib	}
564161310Snetchild
565195104Srwatson	AUDIT_ARG_PROCESS(p);
566184058Skib	error = p_cansignal(td, p, signum);
567200667Skib	if (error != 0 || signum == 0)
568184058Skib		goto out;
569161310Snetchild
570184058Skib	error = ESRCH;
571165869Snetchild	em = em_find(p, EMUL_DONTLOCK);
572161310Snetchild
573161310Snetchild	if (em == NULL) {
574161310Snetchild#ifdef DEBUG
575184058Skib		printf("emuldata not found in do_tkill.\n");
576161310Snetchild#endif
577184058Skib		goto out;
578161310Snetchild	}
579184058Skib	if (tgid > 0 && em->shared->group_pid != tgid)
580184058Skib		goto out;
581161310Snetchild
582184058Skib	ksiginfo_init(&ksi);
583184058Skib	ksi.ksi_signo = signum;
584184058Skib	ksi.ksi_code = LINUX_SI_TKILL;
585184058Skib	ksi.ksi_errno = 0;
586184058Skib	ksi.ksi_pid = proc->p_pid;
587184058Skib	ksi.ksi_uid = proc->p_ucred->cr_ruid;
588161310Snetchild
589209592Sjhb	error = pksignal(p, ksi.ksi_signo, &ksi);
590184058Skib
591184058Skibout:
592184058Skib	PROC_UNLOCK(p);
593184058Skib	return (error);
594161310Snetchild}
595161310Snetchild
596161310Snetchildint
597184058Skiblinux_tgkill(struct thread *td, struct linux_tgkill_args *args)
598184058Skib{
599184058Skib
600184058Skib#ifdef DEBUG
601184058Skib	if (ldebug(tgkill))
602184058Skib		printf(ARGS(tgkill, "%d, %d, %d"), args->tgid, args->pid, args->sig);
603184058Skib#endif
604184058Skib	if (args->pid <= 0 || args->tgid <=0)
605184058Skib		return (EINVAL);
606184058Skib
607184058Skib	return (linux_do_tkill(td, args->tgid, args->pid, args->sig));
608184058Skib}
609184058Skib
610184058Skibint
611161310Snetchildlinux_tkill(struct thread *td, struct linux_tkill_args *args)
612161310Snetchild{
613161310Snetchild#ifdef DEBUG
614161310Snetchild	if (ldebug(tkill))
615161310Snetchild		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
616161310Snetchild#endif
617184058Skib	if (args->tid <= 0)
618184058Skib		return (EINVAL);
619161310Snetchild
620184058Skib	return (linux_do_tkill(td, 0, args->tid, args->sig));
621161310Snetchild}
622184058Skib
623184058Skibvoid
624184058Skibksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
625184058Skib{
626184058Skib
627184058Skib	lsi->lsi_signo = sig;
628184058Skib	lsi->lsi_code = ksi->ksi_code;
629184058Skib
630184058Skib	switch (sig) {
631184058Skib	case LINUX_SIGPOLL:
632184058Skib		/* XXX si_fd? */
633184058Skib		lsi->lsi_band = ksi->ksi_band;
634184058Skib		break;
635184058Skib	case LINUX_SIGCHLD:
636184058Skib		lsi->lsi_pid = ksi->ksi_pid;
637184058Skib		lsi->lsi_uid = ksi->ksi_uid;
638184058Skib		lsi->lsi_status = ksi->ksi_status;
639184058Skib		break;
640184058Skib	case LINUX_SIGBUS:
641184058Skib	case LINUX_SIGILL:
642184058Skib	case LINUX_SIGFPE:
643184058Skib	case LINUX_SIGSEGV:
644184058Skib		lsi->lsi_addr = PTROUT(ksi->ksi_addr);
645184058Skib		break;
646184058Skib	default:
647184058Skib		/* XXX SI_TIMER etc... */
648184058Skib		lsi->lsi_pid = ksi->ksi_pid;
649184058Skib		lsi->lsi_uid = ksi->ksi_uid;
650184058Skib		break;
651184058Skib	}
652218720Sdchagin	if (sig >= LINUX_SIGRTMIN) {
653218720Sdchagin		lsi->lsi_int = ksi->ksi_info.si_value.sival_int;
654218720Sdchagin		lsi->lsi_ptr = PTROUT(ksi->ksi_info.si_value.sival_ptr);
655218720Sdchagin	}
656184058Skib}
657