xref: /freebsd/sys/compat/linux/linux_signal.c (revision dc319d05aec8408641320dc12ff93370b6640265)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1994-1995 Søren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/sx.h>
37 #include <sys/proc.h>
38 #include <sys/signalvar.h>
39 #include <sys/syscallsubr.h>
40 #include <sys/sysproto.h>
41 
42 #include <security/audit/audit.h>
43 
44 #include "opt_compat.h"
45 
46 #ifdef COMPAT_LINUX32
47 #include <machine/../linux32/linux.h>
48 #include <machine/../linux32/linux32_proto.h>
49 #else
50 #include <machine/../linux/linux.h>
51 #include <machine/../linux/linux_proto.h>
52 #endif
53 #include <compat/linux/linux_signal.h>
54 #include <compat/linux/linux_util.h>
55 #include <compat/linux/linux_emul.h>
56 #include <compat/linux/linux_misc.h>
57 
58 static int	linux_do_tkill(struct thread *td, struct thread *tdt,
59 		    ksiginfo_t *ksi);
60 static void	sicode_to_lsicode(int si_code, int *lsi_code);
61 
62 
63 static void
64 linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
65 {
66 	unsigned long flags;
67 
68 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
69 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
70 	bsa->sa_flags = 0;
71 
72 	flags = lsa->lsa_flags;
73 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
74 		flags &= ~LINUX_SA_NOCLDSTOP;
75 		bsa->sa_flags |= SA_NOCLDSTOP;
76 	}
77 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
78 		flags &= ~LINUX_SA_NOCLDWAIT;
79 		bsa->sa_flags |= SA_NOCLDWAIT;
80 	}
81 	if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
82 		flags &= ~LINUX_SA_SIGINFO;
83 		bsa->sa_flags |= SA_SIGINFO;
84 #ifdef notyet
85 		/*
86 		 * XXX: We seem to be missing code to convert
87 		 *      some of the fields in ucontext_t.
88 		 */
89 		linux_msg(curthread,
90 		    "partially unsupported sigaction flag SA_SIGINFO");
91 #endif
92 	}
93 	if (lsa->lsa_flags & LINUX_SA_RESTORER) {
94 		flags &= ~LINUX_SA_RESTORER;
95 		/* XXX: We might want to handle it; see Linux sigreturn(2). */
96 	}
97 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
98 		flags &= ~LINUX_SA_ONSTACK;
99 		bsa->sa_flags |= SA_ONSTACK;
100 	}
101 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
102 		flags &= ~LINUX_SA_RESTART;
103 		bsa->sa_flags |= SA_RESTART;
104 	}
105 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
106 		flags &= ~LINUX_SA_ONESHOT;
107 		bsa->sa_flags |= SA_RESETHAND;
108 	}
109 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
110 		flags &= ~LINUX_SA_NOMASK;
111 		bsa->sa_flags |= SA_NODEFER;
112 	}
113 
114 	if (flags != 0)
115 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
116 }
117 
118 static void
119 bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
120 {
121 
122 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
123 #ifdef COMPAT_LINUX32
124 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
125 #else
126 	lsa->lsa_handler = bsa->sa_handler;
127 #endif
128 	lsa->lsa_restorer = 0;		/* unsupported */
129 	lsa->lsa_flags = 0;
130 	if (bsa->sa_flags & SA_NOCLDSTOP)
131 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
132 	if (bsa->sa_flags & SA_NOCLDWAIT)
133 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
134 	if (bsa->sa_flags & SA_SIGINFO)
135 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
136 	if (bsa->sa_flags & SA_ONSTACK)
137 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
138 	if (bsa->sa_flags & SA_RESTART)
139 		lsa->lsa_flags |= LINUX_SA_RESTART;
140 	if (bsa->sa_flags & SA_RESETHAND)
141 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
142 	if (bsa->sa_flags & SA_NODEFER)
143 		lsa->lsa_flags |= LINUX_SA_NOMASK;
144 }
145 
146 int
147 linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
148 		   l_sigaction_t *linux_osa)
149 {
150 	struct sigaction act, oact, *nsa, *osa;
151 	int error, sig;
152 
153 	if (!LINUX_SIG_VALID(linux_sig))
154 		return (EINVAL);
155 
156 	osa = (linux_osa != NULL) ? &oact : NULL;
157 	if (linux_nsa != NULL) {
158 		nsa = &act;
159 		linux_to_bsd_sigaction(linux_nsa, nsa);
160 	} else
161 		nsa = NULL;
162 	sig = linux_to_bsd_signal(linux_sig);
163 
164 	error = kern_sigaction(td, sig, nsa, osa, 0);
165 	if (error)
166 		return (error);
167 
168 	if (linux_osa != NULL)
169 		bsd_to_linux_sigaction(osa, linux_osa);
170 
171 	return (0);
172 }
173 
174 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
175 int
176 linux_signal(struct thread *td, struct linux_signal_args *args)
177 {
178 	l_sigaction_t nsa, osa;
179 	int error;
180 
181 	nsa.lsa_handler = args->handler;
182 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
183 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
184 
185 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
186 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
187 
188 	return (error);
189 }
190 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
191 
192 int
193 linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
194 {
195 	l_sigaction_t nsa, osa;
196 	int error;
197 
198 	if (args->sigsetsize != sizeof(l_sigset_t))
199 		return (EINVAL);
200 
201 	if (args->act != NULL) {
202 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
203 		if (error)
204 			return (error);
205 	}
206 
207 	error = linux_do_sigaction(td, args->sig,
208 				   args->act ? &nsa : NULL,
209 				   args->oact ? &osa : NULL);
210 
211 	if (args->oact != NULL && !error) {
212 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
213 	}
214 
215 	return (error);
216 }
217 
218 static int
219 linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
220 		     l_sigset_t *old)
221 {
222 	sigset_t omask, nmask;
223 	sigset_t *nmaskp;
224 	int error;
225 
226 	td->td_retval[0] = 0;
227 
228 	switch (how) {
229 	case LINUX_SIG_BLOCK:
230 		how = SIG_BLOCK;
231 		break;
232 	case LINUX_SIG_UNBLOCK:
233 		how = SIG_UNBLOCK;
234 		break;
235 	case LINUX_SIG_SETMASK:
236 		how = SIG_SETMASK;
237 		break;
238 	default:
239 		return (EINVAL);
240 	}
241 	if (new != NULL) {
242 		linux_to_bsd_sigset(new, &nmask);
243 		nmaskp = &nmask;
244 	} else
245 		nmaskp = NULL;
246 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
247 	if (error == 0 && old != NULL)
248 		bsd_to_linux_sigset(&omask, old);
249 
250 	return (error);
251 }
252 
253 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
254 int
255 linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
256 {
257 	l_osigset_t mask;
258 	l_sigset_t set, oset;
259 	int error;
260 
261 	if (args->mask != NULL) {
262 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
263 		if (error)
264 			return (error);
265 		LINUX_SIGEMPTYSET(set);
266 		set.__mask = mask;
267 	}
268 
269 	error = linux_do_sigprocmask(td, args->how,
270 				     args->mask ? &set : NULL,
271 				     args->omask ? &oset : NULL);
272 
273 	if (args->omask != NULL && !error) {
274 		mask = oset.__mask;
275 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
276 	}
277 
278 	return (error);
279 }
280 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
281 
282 int
283 linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
284 {
285 	l_sigset_t set, oset;
286 	int error;
287 
288 	if (args->sigsetsize != sizeof(l_sigset_t))
289 		return (EINVAL);
290 
291 	if (args->mask != NULL) {
292 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
293 		if (error)
294 			return (error);
295 	}
296 
297 	error = linux_do_sigprocmask(td, args->how,
298 				     args->mask ? &set : NULL,
299 				     args->omask ? &oset : NULL);
300 
301 	if (args->omask != NULL && !error) {
302 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
303 	}
304 
305 	return (error);
306 }
307 
308 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
309 int
310 linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
311 {
312 	struct proc *p = td->td_proc;
313 	l_sigset_t mask;
314 
315 	PROC_LOCK(p);
316 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
317 	PROC_UNLOCK(p);
318 	td->td_retval[0] = mask.__mask;
319 	return (0);
320 }
321 
322 int
323 linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
324 {
325 	struct proc *p = td->td_proc;
326 	l_sigset_t lset;
327 	sigset_t bset;
328 
329 	PROC_LOCK(p);
330 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
331 	td->td_retval[0] = lset.__mask;
332 	LINUX_SIGEMPTYSET(lset);
333 	lset.__mask = args->mask;
334 	linux_to_bsd_sigset(&lset, &bset);
335 	td->td_sigmask = bset;
336 	SIG_CANTMASK(td->td_sigmask);
337 	signotify(td);
338 	PROC_UNLOCK(p);
339 	return (0);
340 }
341 
342 int
343 linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
344 {
345 	struct proc *p = td->td_proc;
346 	sigset_t bset;
347 	l_sigset_t lset;
348 	l_osigset_t mask;
349 
350 	PROC_LOCK(p);
351 	bset = p->p_siglist;
352 	SIGSETOR(bset, td->td_siglist);
353 	SIGSETAND(bset, td->td_sigmask);
354 	PROC_UNLOCK(p);
355 	bsd_to_linux_sigset(&bset, &lset);
356 	mask = lset.__mask;
357 	return (copyout(&mask, args->mask, sizeof(mask)));
358 }
359 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
360 
361 /*
362  * MPSAFE
363  */
364 int
365 linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
366 {
367 	struct proc *p = td->td_proc;
368 	sigset_t bset;
369 	l_sigset_t lset;
370 
371 	if (args->sigsetsize > sizeof(lset))
372 		return (EINVAL);
373 		/* NOT REACHED */
374 
375 	PROC_LOCK(p);
376 	bset = p->p_siglist;
377 	SIGSETOR(bset, td->td_siglist);
378 	SIGSETAND(bset, td->td_sigmask);
379 	PROC_UNLOCK(p);
380 	bsd_to_linux_sigset(&bset, &lset);
381 	return (copyout(&lset, args->set, args->sigsetsize));
382 }
383 
384 /*
385  * MPSAFE
386  */
387 int
388 linux_rt_sigtimedwait(struct thread *td,
389 	struct linux_rt_sigtimedwait_args *args)
390 {
391 	int error, sig;
392 	l_timeval ltv;
393 	struct timeval tv;
394 	struct timespec ts, *tsa;
395 	l_sigset_t lset;
396 	sigset_t bset;
397 	l_siginfo_t linfo;
398 	ksiginfo_t info;
399 
400 	if (args->sigsetsize != sizeof(l_sigset_t))
401 		return (EINVAL);
402 
403 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
404 		return (error);
405 	linux_to_bsd_sigset(&lset, &bset);
406 
407 	tsa = NULL;
408 	if (args->timeout) {
409 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
410 			return (error);
411 		tv.tv_sec = (long)ltv.tv_sec;
412 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
413 		if (itimerfix(&tv)) {
414 			/*
415 			 * The timeout was invalid. Convert it to something
416 			 * valid that will act as it does under Linux.
417 			 */
418 			tv.tv_sec += tv.tv_usec / 1000000;
419 			tv.tv_usec %= 1000000;
420 			if (tv.tv_usec < 0) {
421 				tv.tv_sec -= 1;
422 				tv.tv_usec += 1000000;
423 			}
424 			if (tv.tv_sec < 0)
425 				timevalclear(&tv);
426 		}
427 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
428 		tsa = &ts;
429 	}
430 	error = kern_sigtimedwait(td, bset, &info, tsa);
431 	if (error)
432 		return (error);
433 
434 	sig = bsd_to_linux_signal(info.ksi_signo);
435 
436 	if (args->ptr) {
437 		memset(&linfo, 0, sizeof(linfo));
438 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
439 		error = copyout(&linfo, args->ptr, sizeof(linfo));
440 	}
441 	if (error == 0)
442 		td->td_retval[0] = sig;
443 
444 	return (error);
445 }
446 
447 int
448 linux_kill(struct thread *td, struct linux_kill_args *args)
449 {
450 	int l_signum;
451 
452 	/*
453 	 * Allow signal 0 as a means to check for privileges
454 	 */
455 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
456 		return (EINVAL);
457 
458 	if (args->signum > 0)
459 		l_signum = linux_to_bsd_signal(args->signum);
460 	else
461 		l_signum = 0;
462 
463 	return (kern_kill(td, args->pid, l_signum));
464 }
465 
466 static int
467 linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
468 {
469 	struct proc *p;
470 	int error;
471 
472 	p = tdt->td_proc;
473 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
474 	AUDIT_ARG_PID(p->p_pid);
475 	AUDIT_ARG_PROCESS(p);
476 
477 	error = p_cansignal(td, p, ksi->ksi_signo);
478 	if (error != 0 || ksi->ksi_signo == 0)
479 		goto out;
480 
481 	tdksignal(tdt, ksi->ksi_signo, ksi);
482 
483 out:
484 	PROC_UNLOCK(p);
485 	return (error);
486 }
487 
488 int
489 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
490 {
491 	struct thread *tdt;
492 	ksiginfo_t ksi;
493 	int sig;
494 
495 	if (args->pid <= 0 || args->tgid <=0)
496 		return (EINVAL);
497 
498 	/*
499 	 * Allow signal 0 as a means to check for privileges
500 	 */
501 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
502 		return (EINVAL);
503 
504 	if (args->sig > 0)
505 		sig = linux_to_bsd_signal(args->sig);
506 	else
507 		sig = 0;
508 
509 	tdt = linux_tdfind(td, args->pid, args->tgid);
510 	if (tdt == NULL)
511 		return (ESRCH);
512 
513 	ksiginfo_init(&ksi);
514 	ksi.ksi_signo = sig;
515 	ksi.ksi_code = SI_LWP;
516 	ksi.ksi_errno = 0;
517 	ksi.ksi_pid = td->td_proc->p_pid;
518 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
519 	return (linux_do_tkill(td, tdt, &ksi));
520 }
521 
522 /*
523  * Deprecated since 2.5.75. Replaced by tgkill().
524  */
525 int
526 linux_tkill(struct thread *td, struct linux_tkill_args *args)
527 {
528 	struct thread *tdt;
529 	ksiginfo_t ksi;
530 	int sig;
531 
532 	if (args->tid <= 0)
533 		return (EINVAL);
534 
535 	if (!LINUX_SIG_VALID(args->sig))
536 		return (EINVAL);
537 
538 	sig = linux_to_bsd_signal(args->sig);
539 
540 	tdt = linux_tdfind(td, args->tid, -1);
541 	if (tdt == NULL)
542 		return (ESRCH);
543 
544 	ksiginfo_init(&ksi);
545 	ksi.ksi_signo = sig;
546 	ksi.ksi_code = SI_LWP;
547 	ksi.ksi_errno = 0;
548 	ksi.ksi_pid = td->td_proc->p_pid;
549 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
550 	return (linux_do_tkill(td, tdt, &ksi));
551 }
552 
553 void
554 ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
555 {
556 
557 	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
558 }
559 
560 static void
561 sicode_to_lsicode(int si_code, int *lsi_code)
562 {
563 
564 	switch (si_code) {
565 	case SI_USER:
566 		*lsi_code = LINUX_SI_USER;
567 		break;
568 	case SI_KERNEL:
569 		*lsi_code = LINUX_SI_KERNEL;
570 		break;
571 	case SI_QUEUE:
572 		*lsi_code = LINUX_SI_QUEUE;
573 		break;
574 	case SI_TIMER:
575 		*lsi_code = LINUX_SI_TIMER;
576 		break;
577 	case SI_MESGQ:
578 		*lsi_code = LINUX_SI_MESGQ;
579 		break;
580 	case SI_ASYNCIO:
581 		*lsi_code = LINUX_SI_ASYNCIO;
582 		break;
583 	case SI_LWP:
584 		*lsi_code = LINUX_SI_TKILL;
585 		break;
586 	default:
587 		*lsi_code = si_code;
588 		break;
589 	}
590 }
591 
592 void
593 siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
594 {
595 
596 	/* sig alredy converted */
597 	lsi->lsi_signo = sig;
598 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
599 
600 	switch (si->si_code) {
601 	case SI_LWP:
602 		lsi->lsi_pid = si->si_pid;
603 		lsi->lsi_uid = si->si_uid;
604 		break;
605 
606 	case SI_TIMER:
607 		lsi->lsi_int = si->si_value.sival_int;
608 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
609 		lsi->lsi_tid = si->si_timerid;
610 		break;
611 
612 	case SI_QUEUE:
613 		lsi->lsi_pid = si->si_pid;
614 		lsi->lsi_uid = si->si_uid;
615 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
616 		break;
617 
618 	case SI_ASYNCIO:
619 		lsi->lsi_int = si->si_value.sival_int;
620 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
621 		break;
622 
623 	default:
624 		switch (sig) {
625 		case LINUX_SIGPOLL:
626 			/* XXX si_fd? */
627 			lsi->lsi_band = si->si_band;
628 			break;
629 
630 		case LINUX_SIGCHLD:
631 			lsi->lsi_errno = 0;
632 			lsi->lsi_pid = si->si_pid;
633 			lsi->lsi_uid = si->si_uid;
634 
635 			if (si->si_code == CLD_STOPPED)
636 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
637 			else if (si->si_code == CLD_CONTINUED)
638 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
639 			else
640 				lsi->lsi_status = si->si_status;
641 			break;
642 
643 		case LINUX_SIGBUS:
644 		case LINUX_SIGILL:
645 		case LINUX_SIGFPE:
646 		case LINUX_SIGSEGV:
647 			lsi->lsi_addr = PTROUT(si->si_addr);
648 			break;
649 
650 		default:
651 			lsi->lsi_pid = si->si_pid;
652 			lsi->lsi_uid = si->si_uid;
653 			if (sig >= LINUX_SIGRTMIN) {
654 				lsi->lsi_int = si->si_value.sival_int;
655 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
656 			}
657 			break;
658 		}
659 		break;
660 	}
661 }
662 
663 void
664 lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
665 {
666 
667 	ksi->ksi_signo = sig;
668 	ksi->ksi_code = lsi->lsi_code;	/* XXX. Convert. */
669 	ksi->ksi_pid = lsi->lsi_pid;
670 	ksi->ksi_uid = lsi->lsi_uid;
671 	ksi->ksi_status = lsi->lsi_status;
672 	ksi->ksi_addr = PTRIN(lsi->lsi_addr);
673 	ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
674 }
675 
676 int
677 linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
678 {
679 	l_siginfo_t linfo;
680 	struct proc *p;
681 	ksiginfo_t ksi;
682 	int error;
683 	int sig;
684 
685 	if (!LINUX_SIG_VALID(args->sig))
686 		return (EINVAL);
687 
688 	error = copyin(args->info, &linfo, sizeof(linfo));
689 	if (error != 0)
690 		return (error);
691 
692 	if (linfo.lsi_code >= 0)
693 		return (EPERM);
694 
695 	sig = linux_to_bsd_signal(args->sig);
696 
697 	error = ESRCH;
698 	if ((p = pfind_any(args->pid)) != NULL) {
699 		error = p_cansignal(td, p, sig);
700 		if (error != 0) {
701 			PROC_UNLOCK(p);
702 			return (error);
703 		}
704 
705 		ksiginfo_init(&ksi);
706 		lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
707 		error = tdsendsignal(p, NULL, sig, &ksi);
708 		PROC_UNLOCK(p);
709 	}
710 
711 	return (error);
712 }
713 
714 int
715 linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
716 {
717 	l_siginfo_t linfo;
718 	struct thread *tds;
719 	ksiginfo_t ksi;
720 	int error;
721 	int sig;
722 
723 	if (!LINUX_SIG_VALID(args->sig))
724 		return (EINVAL);
725 
726 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
727 	if (error != 0)
728 		return (error);
729 
730 	if (linfo.lsi_code >= 0)
731 		return (EPERM);
732 
733 	tds = linux_tdfind(td, args->tid, args->tgid);
734 	if (tds == NULL)
735 		return (ESRCH);
736 
737 	sig = linux_to_bsd_signal(args->sig);
738 	ksiginfo_init(&ksi);
739 	lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
740 	return (linux_do_tkill(td, tds, &ksi));
741 }
742