linux_signal.c revision 293498
1139749Simp/*-
2102445Sjhb * Copyright (c) 1994-1995 S��ren Schmidt
3102445Sjhb * All rights reserved.
4102445Sjhb *
5102445Sjhb * Redistribution and use in source and binary forms, with or without
6102445Sjhb * modification, are permitted provided that the following conditions
7102445Sjhb * are met:
8102445Sjhb * 1. Redistributions of source code must retain the above copyright
9102445Sjhb *    notice, this list of conditions and the following disclaimer
10102445Sjhb *    in this position and unchanged.
11102445Sjhb * 2. Redistributions in binary form must reproduce the above copyright
12102445Sjhb *    notice, this list of conditions and the following disclaimer in the
13102445Sjhb *    documentation and/or other materials provided with the distribution.
14102445Sjhb * 3. The name of the author may not be used to endorse or promote products
15102445Sjhb *    derived from this software without specific prior written permission
16102445Sjhb *
17102445Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18102445Sjhb * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19102445Sjhb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20102445Sjhb * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21102445Sjhb * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22102445Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23102445Sjhb * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24102445Sjhb * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25102445Sjhb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26102445Sjhb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27102445Sjhb */
28102445Sjhb
29119418Sobrien#include <sys/cdefs.h>
30119418Sobrien__FBSDID("$FreeBSD: stable/10/sys/compat/linux/linux_signal.c 293498 2016-01-09 15:21:45Z dchagin $");
31119418Sobrien
32259512Skib#include <sys/param.h>
33259512Skib#include <sys/systm.h>
34102445Sjhb#include <sys/lock.h>
35102445Sjhb#include <sys/mutex.h>
36102445Sjhb#include <sys/sx.h>
37102445Sjhb#include <sys/proc.h>
38102445Sjhb#include <sys/signalvar.h>
39102445Sjhb#include <sys/syscallsubr.h>
40102445Sjhb#include <sys/sysproto.h>
41193530Sjkim
42193530Sjkim#include <security/audit/audit.h>
43193530Sjkim
44102445Sjhb#include "opt_compat.h"
45102445Sjhb
46102445Sjhb#ifdef COMPAT_LINUX32
47102445Sjhb#include <machine/../linux32/linux.h>
48102445Sjhb#include <machine/../linux32/linux32_proto.h>
49102445Sjhb#else
50102445Sjhb#include <machine/../linux/linux.h>
51102445Sjhb#include <machine/../linux/linux_proto.h>
52102445Sjhb#endif
53102445Sjhb#include <compat/linux/linux_signal.h>
54129829Snjl#include <compat/linux/linux_util.h>
55102445Sjhb#include <compat/linux/linux_emul.h>
56102445Sjhb#include <compat/linux/linux_misc.h>
57102445Sjhb
58102445Sjhbstatic int	linux_do_tkill(struct thread *td, struct thread *tdt,
59129829Snjl		    ksiginfo_t *ksi);
60129829Snjlstatic void	sicode_to_lsicode(int si_code, int *lsi_code);
61131341Snjl
62102445Sjhb
63102445Sjhbvoid
64133619Snjllinux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
65133619Snjl{
66138200Snjl	int b, l;
67138200Snjl
68138200Snjl	SIGEMPTYSET(*bss);
69138200Snjl	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
70138200Snjl	bss->__bits[1] = lss->__bits[1];
71138200Snjl	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
72130978Sjhb		if (LINUX_SIGISMEMBER(*lss, l)) {
73130978Sjhb			b = linux_to_bsd_signal[_SIG_IDX(l)];
74130978Sjhb			if (b)
75102445Sjhb				SIGADDSET(*bss, b);
76102445Sjhb		}
77129829Snjl	}
78131341Snjl}
79131341Snjl
80130978Sjhbvoid
81130978Sjhbbsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
82102445Sjhb{
83129829Snjl	int b, l;
84130978Sjhb
85259512Skib	LINUX_SIGEMPTYSET(*lss);
86102445Sjhb	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
87102445Sjhb	lss->__bits[1] = bss->__bits[1];
88102445Sjhb	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
89102445Sjhb		if (SIGISMEMBER(*bss, b)) {
90102445Sjhb			l = bsd_to_linux_signal[_SIG_IDX(b)];
91102445Sjhb			if (l)
92102445Sjhb				LINUX_SIGADDSET(*lss, l);
93102445Sjhb		}
94131341Snjl	}
95127680Stakawata}
96259512Skib
97102445Sjhbstatic void
98102445Sjhblinux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
99128016Sjhb{
100102445Sjhb
101246128Ssbz	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
102102445Sjhb	bsa->sa_handler = PTRIN(lsa->lsa_handler);
103102445Sjhb	bsa->sa_flags = 0;
104154600Sjhb	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
105102445Sjhb		bsa->sa_flags |= SA_NOCLDSTOP;
106232403Sjhb	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
107232403Sjhb		bsa->sa_flags |= SA_NOCLDWAIT;
108102445Sjhb	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
109128071Snjl		bsa->sa_flags |= SA_SIGINFO;
110128071Snjl	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
111102445Sjhb		bsa->sa_flags |= SA_ONSTACK;
112102445Sjhb	if (lsa->lsa_flags & LINUX_SA_RESTART)
113102445Sjhb		bsa->sa_flags |= SA_RESTART;
114102445Sjhb	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
115102445Sjhb		bsa->sa_flags |= SA_RESETHAND;
116102445Sjhb	if (lsa->lsa_flags & LINUX_SA_NOMASK)
117102445Sjhb		bsa->sa_flags |= SA_NODEFER;
118131341Snjl}
119102445Sjhb
120127681Snjlstatic void
121102445Sjhbbsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
122127681Snjl{
123131341Snjl
124131341Snjl	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
125131341Snjl#ifdef COMPAT_LINUX32
126102445Sjhb	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
127127681Snjl#else
128102445Sjhb	lsa->lsa_handler = bsa->sa_handler;
129102445Sjhb#endif
130127680Stakawata	lsa->lsa_restorer = 0;		/* unsupported */
131131341Snjl	lsa->lsa_flags = 0;
132131341Snjl	if (bsa->sa_flags & SA_NOCLDSTOP)
133131341Snjl		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
134131341Snjl	if (bsa->sa_flags & SA_NOCLDWAIT)
135131341Snjl		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
136131341Snjl	if (bsa->sa_flags & SA_SIGINFO)
137131341Snjl		lsa->lsa_flags |= LINUX_SA_SIGINFO;
138131341Snjl	if (bsa->sa_flags & SA_ONSTACK)
139131341Snjl		lsa->lsa_flags |= LINUX_SA_ONSTACK;
140131341Snjl	if (bsa->sa_flags & SA_RESTART)
141131341Snjl		lsa->lsa_flags |= LINUX_SA_RESTART;
142131341Snjl	if (bsa->sa_flags & SA_RESETHAND)
143131341Snjl		lsa->lsa_flags |= LINUX_SA_ONESHOT;
144131341Snjl	if (bsa->sa_flags & SA_NODEFER)
145131341Snjl		lsa->lsa_flags |= LINUX_SA_NOMASK;
146131341Snjl}
147131341Snjl
148127680Stakawataint
149127680Stakawatalinux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
150127680Stakawata		   l_sigaction_t *linux_osa)
151127680Stakawata{
152127681Snjl	struct sigaction act, oact, *nsa, *osa;
153127680Stakawata	int error, sig;
154127680Stakawata
155127681Snjl	if (!LINUX_SIG_VALID(linux_sig))
156132136Stakawata		return (EINVAL);
157127680Stakawata
158127680Stakawata	osa = (linux_osa != NULL) ? &oact : NULL;
159127680Stakawata	if (linux_nsa != NULL) {
160127680Stakawata		nsa = &act;
161127680Stakawata		linux_to_bsd_sigaction(linux_nsa, nsa);
162102445Sjhb	} else
163102445Sjhb		nsa = NULL;
164102445Sjhb
165102445Sjhb	if (linux_sig <= LINUX_SIGTBLSZ)
166102445Sjhb		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
167102445Sjhb	else
168128247Snjl		sig = linux_sig;
169128016Sjhb
170138200Snjl	error = kern_sigaction(td, sig, nsa, osa, 0);
171102445Sjhb	if (error)
172133619Snjl		return (error);
173138200Snjl
174128016Sjhb	if (linux_osa != NULL)
175128016Sjhb		bsd_to_linux_sigaction(osa, linux_osa);
176128016Sjhb
177128016Sjhb	return (0);
178128016Sjhb}
179128016Sjhb
180128016Sjhb
181128016Sjhbint
182128016Sjhblinux_signal(struct thread *td, struct linux_signal_args *args)
183128016Sjhb{
184128016Sjhb	l_sigaction_t nsa, osa;
185133619Snjl	int error;
186128016Sjhb
187214110Sjkim#ifdef DEBUG
188128016Sjhb	if (ldebug(signal))
189128016Sjhb		printf(ARGS(signal, "%d, %p"),
190133619Snjl		    args->sig, (void *)(uintptr_t)args->handler);
191128016Sjhb#endif
192130210Snjl
193138200Snjl	nsa.lsa_handler = args->handler;
194214072Sjkim	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
195214072Sjkim	LINUX_SIGEMPTYSET(nsa.lsa_mask);
196214072Sjkim
197214072Sjkim	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
198214072Sjkim	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
199130208Snjl
200214072Sjkim	return (error);
201138200Snjl}
202214068Sjkim
203133619Snjlint
204133619Snjllinux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
205133619Snjl{
206133619Snjl	l_sigaction_t nsa, osa;
207133619Snjl	int error;
208102445Sjhb
209102445Sjhb#ifdef DEBUG
210130978Sjhb	if (ldebug(rt_sigaction))
211130978Sjhb		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
212130978Sjhb		    (long)args->sig, (void *)args->act,
213130978Sjhb		    (void *)args->oact, (long)args->sigsetsize);
214130978Sjhb#endif
215130978Sjhb
216130978Sjhb	if (args->sigsetsize != sizeof(l_sigset_t))
217223207Sjhb		return (EINVAL);
218223207Sjhb
219223207Sjhb	if (args->act != NULL) {
220223207Sjhb		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
221223207Sjhb		if (error)
222130978Sjhb			return (error);
223130978Sjhb	}
224130978Sjhb
225130978Sjhb	error = linux_do_sigaction(td, args->sig,
226130978Sjhb				   args->act ? &nsa : NULL,
227130978Sjhb				   args->oact ? &osa : NULL);
228130978Sjhb
229223207Sjhb	if (args->oact != NULL && !error) {
230130978Sjhb		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
231130978Sjhb	}
232130978Sjhb
233130978Sjhb	return (error);
234130978Sjhb}
235131009Snjl
236130978Sjhbstatic int
237130978Sjhblinux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
238130978Sjhb		     l_sigset_t *old)
239130978Sjhb{
240130978Sjhb	sigset_t omask, nmask;
241102445Sjhb	sigset_t *nmaskp;
242102445Sjhb	int error;
243102445Sjhb
244102445Sjhb	td->td_retval[0] = 0;
245102445Sjhb
246102445Sjhb	switch (how) {
247102445Sjhb	case LINUX_SIG_BLOCK:
248102445Sjhb		how = SIG_BLOCK;
249102445Sjhb		break;
250102445Sjhb	case LINUX_SIG_UNBLOCK:
251102445Sjhb		how = SIG_UNBLOCK;
252126560Snjl		break;
253129829Snjl	case LINUX_SIG_SETMASK:
254135574Sjhb		how = SIG_SETMASK;
255135574Sjhb		break;
256102445Sjhb	default:
257129829Snjl		return (EINVAL);
258102445Sjhb	}
259102445Sjhb	if (new != NULL) {
260102445Sjhb		linux_to_bsd_sigset(new, &nmask);
261102445Sjhb		nmaskp = &nmask;
262102445Sjhb	} else
263130978Sjhb		nmaskp = NULL;
264131009Snjl	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
265102445Sjhb	if (error == 0 && old != NULL)
266102445Sjhb		bsd_to_linux_sigset(&omask, old);
267102445Sjhb
268129829Snjl	return (error);
269102445Sjhb}
270102445Sjhb
271102445Sjhbint
272102445Sjhblinux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
273102445Sjhb{
274102445Sjhb	l_osigset_t mask;
275102445Sjhb	l_sigset_t set, oset;
276102445Sjhb	int error;
277129829Snjl
278102445Sjhb#ifdef DEBUG
279102445Sjhb	if (ldebug(sigprocmask))
280102445Sjhb		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
281102445Sjhb#endif
282102445Sjhb
283102445Sjhb	if (args->mask != NULL) {
284232403Sjhb		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
285102445Sjhb		if (error)
286232403Sjhb			return (error);
287232403Sjhb		LINUX_SIGEMPTYSET(set);
288232403Sjhb		set.__bits[0] = mask;
289232403Sjhb	}
290102445Sjhb
291102445Sjhb	error = linux_do_sigprocmask(td, args->how,
292158457Sjhb				     args->mask ? &set : NULL,
293158457Sjhb				     args->omask ? &oset : NULL);
294172394Smarius
295102445Sjhb	if (args->omask != NULL && !error) {
296172394Smarius		mask = oset.__bits[0];
297102445Sjhb		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
298102445Sjhb	}
299102445Sjhb
300102445Sjhb	return (error);
301102445Sjhb}
302102445Sjhb
303102445Sjhbint
304102445Sjhblinux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
305102445Sjhb{
306102445Sjhb	l_sigset_t set, oset;
307102445Sjhb	int error;
308102445Sjhb
309172394Smarius#ifdef DEBUG
310129829Snjl	if (ldebug(rt_sigprocmask))
311199337Sjkim		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
312102445Sjhb		    args->how, (void *)args->mask,
313102445Sjhb		    (void *)args->omask, (long)args->sigsetsize);
314102445Sjhb#endif
315259512Skib
316259512Skib	if (args->sigsetsize != sizeof(l_sigset_t))
317259512Skib		return EINVAL;
318259512Skib
319259512Skib	if (args->mask != NULL) {
320259512Skib		error = copyin(args->mask, &set, sizeof(l_sigset_t));
321259512Skib		if (error)
322259512Skib			return (error);
323259512Skib	}
324259512Skib
325259512Skib	error = linux_do_sigprocmask(td, args->how,
326259512Skib				     args->mask ? &set : NULL,
327259512Skib				     args->omask ? &oset : NULL);
328259512Skib
329259512Skib	if (args->omask != NULL && !error) {
330259512Skib		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
331259512Skib	}
332259512Skib
333259512Skib	return (error);
334259512Skib}
335259512Skib
336259512Skibint
337259512Skiblinux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
338259512Skib{
339259512Skib	struct proc *p = td->td_proc;
340	l_sigset_t mask;
341
342#ifdef DEBUG
343	if (ldebug(sgetmask))
344		printf(ARGS(sgetmask, ""));
345#endif
346
347	PROC_LOCK(p);
348	bsd_to_linux_sigset(&td->td_sigmask, &mask);
349	PROC_UNLOCK(p);
350	td->td_retval[0] = mask.__bits[0];
351	return (0);
352}
353
354int
355linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
356{
357	struct proc *p = td->td_proc;
358	l_sigset_t lset;
359	sigset_t bset;
360
361#ifdef DEBUG
362	if (ldebug(ssetmask))
363		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
364#endif
365
366	PROC_LOCK(p);
367	bsd_to_linux_sigset(&td->td_sigmask, &lset);
368	td->td_retval[0] = lset.__bits[0];
369	LINUX_SIGEMPTYSET(lset);
370	lset.__bits[0] = args->mask;
371	linux_to_bsd_sigset(&lset, &bset);
372	td->td_sigmask = bset;
373	SIG_CANTMASK(td->td_sigmask);
374	signotify(td);
375	PROC_UNLOCK(p);
376	return (0);
377}
378
379/*
380 * MPSAFE
381 */
382int
383linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
384{
385	struct proc *p = td->td_proc;
386	sigset_t bset;
387	l_sigset_t lset;
388	l_osigset_t mask;
389
390#ifdef DEBUG
391	if (ldebug(sigpending))
392		printf(ARGS(sigpending, "*"));
393#endif
394
395	PROC_LOCK(p);
396	bset = p->p_siglist;
397	SIGSETOR(bset, td->td_siglist);
398	SIGSETAND(bset, td->td_sigmask);
399	PROC_UNLOCK(p);
400	bsd_to_linux_sigset(&bset, &lset);
401	mask = lset.__bits[0];
402	return (copyout(&mask, args->mask, sizeof(mask)));
403}
404
405/*
406 * MPSAFE
407 */
408int
409linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
410{
411	struct proc *p = td->td_proc;
412	sigset_t bset;
413	l_sigset_t lset;
414
415	if (args->sigsetsize > sizeof(lset))
416		return EINVAL;
417		/* NOT REACHED */
418
419#ifdef DEBUG
420	if (ldebug(rt_sigpending))
421		printf(ARGS(rt_sigpending, "*"));
422#endif
423
424	PROC_LOCK(p);
425	bset = p->p_siglist;
426	SIGSETOR(bset, td->td_siglist);
427	SIGSETAND(bset, td->td_sigmask);
428	PROC_UNLOCK(p);
429	bsd_to_linux_sigset(&bset, &lset);
430	return (copyout(&lset, args->set, args->sigsetsize));
431}
432
433/*
434 * MPSAFE
435 */
436int
437linux_rt_sigtimedwait(struct thread *td,
438	struct linux_rt_sigtimedwait_args *args)
439{
440	int error, sig;
441	l_timeval ltv;
442	struct timeval tv;
443	struct timespec ts, *tsa;
444	l_sigset_t lset;
445	sigset_t bset;
446	l_siginfo_t linfo;
447	ksiginfo_t info;
448
449#ifdef DEBUG
450	if (ldebug(rt_sigtimedwait))
451		printf(ARGS(rt_sigtimedwait, "*"));
452#endif
453	if (args->sigsetsize != sizeof(l_sigset_t))
454		return (EINVAL);
455
456	if ((error = copyin(args->mask, &lset, sizeof(lset))))
457		return (error);
458	linux_to_bsd_sigset(&lset, &bset);
459
460	tsa = NULL;
461	if (args->timeout) {
462		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
463			return (error);
464#ifdef DEBUG
465		if (ldebug(rt_sigtimedwait))
466			printf(LMSG("linux_rt_sigtimedwait: "
467			    "incoming timeout (%d/%d)\n"),
468			    ltv.tv_sec, ltv.tv_usec);
469#endif
470		tv.tv_sec = (long)ltv.tv_sec;
471		tv.tv_usec = (suseconds_t)ltv.tv_usec;
472		if (itimerfix(&tv)) {
473			/*
474			 * The timeout was invalid. Convert it to something
475			 * valid that will act as it does under Linux.
476			 */
477			tv.tv_sec += tv.tv_usec / 1000000;
478			tv.tv_usec %= 1000000;
479			if (tv.tv_usec < 0) {
480				tv.tv_sec -= 1;
481				tv.tv_usec += 1000000;
482			}
483			if (tv.tv_sec < 0)
484				timevalclear(&tv);
485#ifdef DEBUG
486			if (ldebug(rt_sigtimedwait))
487				printf(LMSG("linux_rt_sigtimedwait: "
488				    "converted timeout (%jd/%ld)\n"),
489				    (intmax_t)tv.tv_sec, tv.tv_usec);
490#endif
491		}
492		TIMEVAL_TO_TIMESPEC(&tv, &ts);
493		tsa = &ts;
494	}
495	error = kern_sigtimedwait(td, bset, &info, tsa);
496#ifdef DEBUG
497	if (ldebug(rt_sigtimedwait))
498		printf(LMSG("linux_rt_sigtimedwait: "
499		    "sigtimedwait returning (%d)\n"), error);
500#endif
501	if (error)
502		return (error);
503
504	sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
505
506	if (args->ptr) {
507		memset(&linfo, 0, sizeof(linfo));
508		ksiginfo_to_lsiginfo(&info, &linfo, sig);
509		error = copyout(&linfo, args->ptr, sizeof(linfo));
510	}
511	if (error == 0)
512		td->td_retval[0] = sig;
513
514	return (error);
515}
516
517int
518linux_kill(struct thread *td, struct linux_kill_args *args)
519{
520	struct kill_args /* {
521	    int pid;
522	    int signum;
523	} */ tmp;
524
525#ifdef DEBUG
526	if (ldebug(kill))
527		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
528#endif
529
530	/*
531	 * Allow signal 0 as a means to check for privileges
532	 */
533	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
534		return (EINVAL);
535
536	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
537		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
538	else
539		tmp.signum = args->signum;
540
541	tmp.pid = args->pid;
542	return (sys_kill(td, &tmp));
543}
544
545static int
546linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
547{
548	struct proc *p;
549	int error;
550
551	p = tdt->td_proc;
552	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
553	AUDIT_ARG_PID(p->p_pid);
554	AUDIT_ARG_PROCESS(p);
555
556	error = p_cansignal(td, p, ksi->ksi_signo);
557	if (error != 0 || ksi->ksi_signo == 0)
558		goto out;
559
560	tdksignal(tdt, ksi->ksi_signo, ksi);
561
562out:
563	PROC_UNLOCK(p);
564	return (error);
565}
566
567int
568linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
569{
570	struct thread *tdt;
571	ksiginfo_t ksi;
572	int sig;
573
574#ifdef DEBUG
575	if (ldebug(tgkill))
576		printf(ARGS(tgkill, "%d, %d, %d"),
577		    args->tgid, args->pid, args->sig);
578#endif
579
580	if (args->pid <= 0 || args->tgid <=0)
581		return (EINVAL);
582
583	/*
584	 * Allow signal 0 as a means to check for privileges
585	 */
586	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
587		return (EINVAL);
588
589	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
590		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
591	else
592		sig = args->sig;
593
594	tdt = linux_tdfind(td, args->pid, args->tgid);
595	if (tdt == NULL)
596		return (ESRCH);
597
598	ksiginfo_init(&ksi);
599	ksi.ksi_signo = sig;
600	ksi.ksi_code = SI_LWP;
601	ksi.ksi_errno = 0;
602	ksi.ksi_pid = td->td_proc->p_pid;
603	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
604	return (linux_do_tkill(td, tdt, &ksi));
605}
606
607/*
608 * Deprecated since 2.5.75. Replaced by tgkill().
609 */
610int
611linux_tkill(struct thread *td, struct linux_tkill_args *args)
612{
613	struct thread *tdt;
614	ksiginfo_t ksi;
615	int sig;
616
617#ifdef DEBUG
618	if (ldebug(tkill))
619		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
620#endif
621	if (args->tid <= 0)
622		return (EINVAL);
623
624	if (!LINUX_SIG_VALID(args->sig))
625		return (EINVAL);
626
627	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
628		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
629	else
630		sig = args->sig;
631
632	tdt = linux_tdfind(td, args->tid, -1);
633	if (tdt == NULL)
634		return (ESRCH);
635
636	ksiginfo_init(&ksi);
637	ksi.ksi_signo = sig;
638	ksi.ksi_code = SI_LWP;
639	ksi.ksi_errno = 0;
640	ksi.ksi_pid = td->td_proc->p_pid;
641	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
642	return (linux_do_tkill(td, tdt, &ksi));
643}
644
645void
646ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
647{
648
649	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
650}
651
652static void
653sicode_to_lsicode(int si_code, int *lsi_code)
654{
655
656	switch (si_code) {
657	case SI_USER:
658		*lsi_code = LINUX_SI_USER;
659		break;
660	case SI_KERNEL:
661		*lsi_code = LINUX_SI_KERNEL;
662		break;
663	case SI_QUEUE:
664		*lsi_code = LINUX_SI_QUEUE;
665		break;
666	case SI_TIMER:
667		*lsi_code = LINUX_SI_TIMER;
668		break;
669	case SI_MESGQ:
670		*lsi_code = LINUX_SI_MESGQ;
671		break;
672	case SI_ASYNCIO:
673		*lsi_code = LINUX_SI_ASYNCIO;
674		break;
675	case SI_LWP:
676		*lsi_code = LINUX_SI_TKILL;
677		break;
678	default:
679		*lsi_code = si_code;
680		break;
681	}
682}
683
684void
685siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
686{
687
688	/* sig alredy converted */
689	lsi->lsi_signo = sig;
690	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
691
692	switch (si->si_code) {
693	case SI_LWP:
694		lsi->lsi_pid = si->si_pid;
695		lsi->lsi_uid = si->si_uid;
696		break;
697
698	case SI_TIMER:
699		lsi->lsi_int = si->si_value.sival_int;
700		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
701		lsi->lsi_tid = si->si_timerid;
702		break;
703
704	case SI_QUEUE:
705		lsi->lsi_pid = si->si_pid;
706		lsi->lsi_uid = si->si_uid;
707		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
708		break;
709
710	case SI_ASYNCIO:
711		lsi->lsi_int = si->si_value.sival_int;
712		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
713		break;
714
715	default:
716		switch (sig) {
717		case LINUX_SIGPOLL:
718			/* XXX si_fd? */
719			lsi->lsi_band = si->si_band;
720			break;
721
722		case LINUX_SIGCHLD:
723			lsi->lsi_errno = 0;
724			lsi->lsi_pid = si->si_pid;
725			lsi->lsi_uid = si->si_uid;
726
727			if (si->si_code == CLD_STOPPED)
728				lsi->lsi_status = BSD_TO_LINUX_SIGNAL(si->si_status);
729			else if (si->si_code == CLD_CONTINUED)
730				lsi->lsi_status = BSD_TO_LINUX_SIGNAL(SIGCONT);
731			else
732				lsi->lsi_status = si->si_status;
733			break;
734
735		case LINUX_SIGBUS:
736		case LINUX_SIGILL:
737		case LINUX_SIGFPE:
738		case LINUX_SIGSEGV:
739			lsi->lsi_addr = PTROUT(si->si_addr);
740			break;
741
742		default:
743			lsi->lsi_pid = si->si_pid;
744			lsi->lsi_uid = si->si_uid;
745			if (sig >= LINUX_SIGRTMIN) {
746				lsi->lsi_int = si->si_value.sival_int;
747				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
748			}
749			break;
750		}
751		break;
752	}
753}
754