xref: /freebsd/sys/compat/linux/linux_signal.c (revision e17f5b1d)
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_INTERRUPT) {
106 		flags &= ~LINUX_SA_INTERRUPT;
107 		/* Documented to be a "historical no-op". */
108 	}
109 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
110 		flags &= ~LINUX_SA_ONESHOT;
111 		bsa->sa_flags |= SA_RESETHAND;
112 	}
113 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
114 		flags &= ~LINUX_SA_NOMASK;
115 		bsa->sa_flags |= SA_NODEFER;
116 	}
117 
118 	if (flags != 0)
119 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
120 }
121 
122 static void
123 bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
124 {
125 
126 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
127 #ifdef COMPAT_LINUX32
128 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
129 #else
130 	lsa->lsa_handler = bsa->sa_handler;
131 #endif
132 	lsa->lsa_restorer = 0;		/* unsupported */
133 	lsa->lsa_flags = 0;
134 	if (bsa->sa_flags & SA_NOCLDSTOP)
135 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
136 	if (bsa->sa_flags & SA_NOCLDWAIT)
137 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
138 	if (bsa->sa_flags & SA_SIGINFO)
139 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
140 	if (bsa->sa_flags & SA_ONSTACK)
141 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
142 	if (bsa->sa_flags & SA_RESTART)
143 		lsa->lsa_flags |= LINUX_SA_RESTART;
144 	if (bsa->sa_flags & SA_RESETHAND)
145 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
146 	if (bsa->sa_flags & SA_NODEFER)
147 		lsa->lsa_flags |= LINUX_SA_NOMASK;
148 }
149 
150 int
151 linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
152 		   l_sigaction_t *linux_osa)
153 {
154 	struct sigaction act, oact, *nsa, *osa;
155 	int error, sig;
156 
157 	if (!LINUX_SIG_VALID(linux_sig))
158 		return (EINVAL);
159 
160 	osa = (linux_osa != NULL) ? &oact : NULL;
161 	if (linux_nsa != NULL) {
162 		nsa = &act;
163 		linux_to_bsd_sigaction(linux_nsa, nsa);
164 	} else
165 		nsa = NULL;
166 	sig = linux_to_bsd_signal(linux_sig);
167 
168 	error = kern_sigaction(td, sig, nsa, osa, 0);
169 	if (error)
170 		return (error);
171 
172 	if (linux_osa != NULL)
173 		bsd_to_linux_sigaction(osa, linux_osa);
174 
175 	return (0);
176 }
177 
178 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
179 int
180 linux_signal(struct thread *td, struct linux_signal_args *args)
181 {
182 	l_sigaction_t nsa, osa;
183 	int error;
184 
185 	nsa.lsa_handler = args->handler;
186 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
187 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
188 
189 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
190 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
191 
192 	return (error);
193 }
194 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
195 
196 int
197 linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
198 {
199 	l_sigaction_t nsa, osa;
200 	int error;
201 
202 	if (args->sigsetsize != sizeof(l_sigset_t))
203 		return (EINVAL);
204 
205 	if (args->act != NULL) {
206 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
207 		if (error)
208 			return (error);
209 	}
210 
211 	error = linux_do_sigaction(td, args->sig,
212 				   args->act ? &nsa : NULL,
213 				   args->oact ? &osa : NULL);
214 
215 	if (args->oact != NULL && !error) {
216 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
217 	}
218 
219 	return (error);
220 }
221 
222 static int
223 linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
224 		     l_sigset_t *old)
225 {
226 	sigset_t omask, nmask;
227 	sigset_t *nmaskp;
228 	int error;
229 
230 	td->td_retval[0] = 0;
231 
232 	switch (how) {
233 	case LINUX_SIG_BLOCK:
234 		how = SIG_BLOCK;
235 		break;
236 	case LINUX_SIG_UNBLOCK:
237 		how = SIG_UNBLOCK;
238 		break;
239 	case LINUX_SIG_SETMASK:
240 		how = SIG_SETMASK;
241 		break;
242 	default:
243 		return (EINVAL);
244 	}
245 	if (new != NULL) {
246 		linux_to_bsd_sigset(new, &nmask);
247 		nmaskp = &nmask;
248 	} else
249 		nmaskp = NULL;
250 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
251 	if (error == 0 && old != NULL)
252 		bsd_to_linux_sigset(&omask, old);
253 
254 	return (error);
255 }
256 
257 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
258 int
259 linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
260 {
261 	l_osigset_t mask;
262 	l_sigset_t set, oset;
263 	int error;
264 
265 	if (args->mask != NULL) {
266 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
267 		if (error)
268 			return (error);
269 		LINUX_SIGEMPTYSET(set);
270 		set.__mask = mask;
271 	}
272 
273 	error = linux_do_sigprocmask(td, args->how,
274 				     args->mask ? &set : NULL,
275 				     args->omask ? &oset : NULL);
276 
277 	if (args->omask != NULL && !error) {
278 		mask = oset.__mask;
279 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
280 	}
281 
282 	return (error);
283 }
284 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
285 
286 int
287 linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
288 {
289 	l_sigset_t set, oset;
290 	int error;
291 
292 	if (args->sigsetsize != sizeof(l_sigset_t))
293 		return (EINVAL);
294 
295 	if (args->mask != NULL) {
296 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
297 		if (error)
298 			return (error);
299 	}
300 
301 	error = linux_do_sigprocmask(td, args->how,
302 				     args->mask ? &set : NULL,
303 				     args->omask ? &oset : NULL);
304 
305 	if (args->omask != NULL && !error) {
306 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
307 	}
308 
309 	return (error);
310 }
311 
312 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
313 int
314 linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
315 {
316 	struct proc *p = td->td_proc;
317 	l_sigset_t mask;
318 
319 	PROC_LOCK(p);
320 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
321 	PROC_UNLOCK(p);
322 	td->td_retval[0] = mask.__mask;
323 	return (0);
324 }
325 
326 int
327 linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
328 {
329 	struct proc *p = td->td_proc;
330 	l_sigset_t lset;
331 	sigset_t bset;
332 
333 	PROC_LOCK(p);
334 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
335 	td->td_retval[0] = lset.__mask;
336 	LINUX_SIGEMPTYSET(lset);
337 	lset.__mask = args->mask;
338 	linux_to_bsd_sigset(&lset, &bset);
339 	td->td_sigmask = bset;
340 	SIG_CANTMASK(td->td_sigmask);
341 	signotify(td);
342 	PROC_UNLOCK(p);
343 	return (0);
344 }
345 
346 int
347 linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
348 {
349 	struct proc *p = td->td_proc;
350 	sigset_t bset;
351 	l_sigset_t lset;
352 	l_osigset_t mask;
353 
354 	PROC_LOCK(p);
355 	bset = p->p_siglist;
356 	SIGSETOR(bset, td->td_siglist);
357 	SIGSETAND(bset, td->td_sigmask);
358 	PROC_UNLOCK(p);
359 	bsd_to_linux_sigset(&bset, &lset);
360 	mask = lset.__mask;
361 	return (copyout(&mask, args->mask, sizeof(mask)));
362 }
363 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
364 
365 /*
366  * MPSAFE
367  */
368 int
369 linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
370 {
371 	struct proc *p = td->td_proc;
372 	sigset_t bset;
373 	l_sigset_t lset;
374 
375 	if (args->sigsetsize > sizeof(lset))
376 		return (EINVAL);
377 		/* NOT REACHED */
378 
379 	PROC_LOCK(p);
380 	bset = p->p_siglist;
381 	SIGSETOR(bset, td->td_siglist);
382 	SIGSETAND(bset, td->td_sigmask);
383 	PROC_UNLOCK(p);
384 	bsd_to_linux_sigset(&bset, &lset);
385 	return (copyout(&lset, args->set, args->sigsetsize));
386 }
387 
388 /*
389  * MPSAFE
390  */
391 int
392 linux_rt_sigtimedwait(struct thread *td,
393 	struct linux_rt_sigtimedwait_args *args)
394 {
395 	int error, sig;
396 	l_timeval ltv;
397 	struct timeval tv;
398 	struct timespec ts, *tsa;
399 	l_sigset_t lset;
400 	sigset_t bset;
401 	l_siginfo_t linfo;
402 	ksiginfo_t info;
403 
404 	if (args->sigsetsize != sizeof(l_sigset_t))
405 		return (EINVAL);
406 
407 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
408 		return (error);
409 	linux_to_bsd_sigset(&lset, &bset);
410 
411 	tsa = NULL;
412 	if (args->timeout) {
413 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
414 			return (error);
415 		tv.tv_sec = (long)ltv.tv_sec;
416 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
417 		if (itimerfix(&tv)) {
418 			/*
419 			 * The timeout was invalid. Convert it to something
420 			 * valid that will act as it does under Linux.
421 			 */
422 			tv.tv_sec += tv.tv_usec / 1000000;
423 			tv.tv_usec %= 1000000;
424 			if (tv.tv_usec < 0) {
425 				tv.tv_sec -= 1;
426 				tv.tv_usec += 1000000;
427 			}
428 			if (tv.tv_sec < 0)
429 				timevalclear(&tv);
430 		}
431 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
432 		tsa = &ts;
433 	}
434 	error = kern_sigtimedwait(td, bset, &info, tsa);
435 	if (error)
436 		return (error);
437 
438 	sig = bsd_to_linux_signal(info.ksi_signo);
439 
440 	if (args->ptr) {
441 		memset(&linfo, 0, sizeof(linfo));
442 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
443 		error = copyout(&linfo, args->ptr, sizeof(linfo));
444 	}
445 	if (error == 0)
446 		td->td_retval[0] = sig;
447 
448 	return (error);
449 }
450 
451 int
452 linux_kill(struct thread *td, struct linux_kill_args *args)
453 {
454 	int l_signum;
455 
456 	/*
457 	 * Allow signal 0 as a means to check for privileges
458 	 */
459 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
460 		return (EINVAL);
461 
462 	if (args->signum > 0)
463 		l_signum = linux_to_bsd_signal(args->signum);
464 	else
465 		l_signum = 0;
466 
467 	return (kern_kill(td, args->pid, l_signum));
468 }
469 
470 static int
471 linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
472 {
473 	struct proc *p;
474 	int error;
475 
476 	p = tdt->td_proc;
477 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
478 	AUDIT_ARG_PID(p->p_pid);
479 	AUDIT_ARG_PROCESS(p);
480 
481 	error = p_cansignal(td, p, ksi->ksi_signo);
482 	if (error != 0 || ksi->ksi_signo == 0)
483 		goto out;
484 
485 	tdksignal(tdt, ksi->ksi_signo, ksi);
486 
487 out:
488 	PROC_UNLOCK(p);
489 	return (error);
490 }
491 
492 int
493 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
494 {
495 	struct thread *tdt;
496 	ksiginfo_t ksi;
497 	int sig;
498 
499 	if (args->pid <= 0 || args->tgid <=0)
500 		return (EINVAL);
501 
502 	/*
503 	 * Allow signal 0 as a means to check for privileges
504 	 */
505 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
506 		return (EINVAL);
507 
508 	if (args->sig > 0)
509 		sig = linux_to_bsd_signal(args->sig);
510 	else
511 		sig = 0;
512 
513 	tdt = linux_tdfind(td, args->pid, args->tgid);
514 	if (tdt == NULL)
515 		return (ESRCH);
516 
517 	ksiginfo_init(&ksi);
518 	ksi.ksi_signo = sig;
519 	ksi.ksi_code = SI_LWP;
520 	ksi.ksi_errno = 0;
521 	ksi.ksi_pid = td->td_proc->p_pid;
522 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
523 	return (linux_do_tkill(td, tdt, &ksi));
524 }
525 
526 /*
527  * Deprecated since 2.5.75. Replaced by tgkill().
528  */
529 int
530 linux_tkill(struct thread *td, struct linux_tkill_args *args)
531 {
532 	struct thread *tdt;
533 	ksiginfo_t ksi;
534 	int sig;
535 
536 	if (args->tid <= 0)
537 		return (EINVAL);
538 
539 	if (!LINUX_SIG_VALID(args->sig))
540 		return (EINVAL);
541 
542 	sig = linux_to_bsd_signal(args->sig);
543 
544 	tdt = linux_tdfind(td, args->tid, -1);
545 	if (tdt == NULL)
546 		return (ESRCH);
547 
548 	ksiginfo_init(&ksi);
549 	ksi.ksi_signo = sig;
550 	ksi.ksi_code = SI_LWP;
551 	ksi.ksi_errno = 0;
552 	ksi.ksi_pid = td->td_proc->p_pid;
553 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
554 	return (linux_do_tkill(td, tdt, &ksi));
555 }
556 
557 void
558 ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
559 {
560 
561 	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
562 }
563 
564 static void
565 sicode_to_lsicode(int si_code, int *lsi_code)
566 {
567 
568 	switch (si_code) {
569 	case SI_USER:
570 		*lsi_code = LINUX_SI_USER;
571 		break;
572 	case SI_KERNEL:
573 		*lsi_code = LINUX_SI_KERNEL;
574 		break;
575 	case SI_QUEUE:
576 		*lsi_code = LINUX_SI_QUEUE;
577 		break;
578 	case SI_TIMER:
579 		*lsi_code = LINUX_SI_TIMER;
580 		break;
581 	case SI_MESGQ:
582 		*lsi_code = LINUX_SI_MESGQ;
583 		break;
584 	case SI_ASYNCIO:
585 		*lsi_code = LINUX_SI_ASYNCIO;
586 		break;
587 	case SI_LWP:
588 		*lsi_code = LINUX_SI_TKILL;
589 		break;
590 	default:
591 		*lsi_code = si_code;
592 		break;
593 	}
594 }
595 
596 void
597 siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
598 {
599 
600 	/* sig alredy converted */
601 	lsi->lsi_signo = sig;
602 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
603 
604 	switch (si->si_code) {
605 	case SI_LWP:
606 		lsi->lsi_pid = si->si_pid;
607 		lsi->lsi_uid = si->si_uid;
608 		break;
609 
610 	case SI_TIMER:
611 		lsi->lsi_int = si->si_value.sival_int;
612 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
613 		lsi->lsi_tid = si->si_timerid;
614 		break;
615 
616 	case SI_QUEUE:
617 		lsi->lsi_pid = si->si_pid;
618 		lsi->lsi_uid = si->si_uid;
619 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
620 		break;
621 
622 	case SI_ASYNCIO:
623 		lsi->lsi_int = si->si_value.sival_int;
624 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
625 		break;
626 
627 	default:
628 		switch (sig) {
629 		case LINUX_SIGPOLL:
630 			/* XXX si_fd? */
631 			lsi->lsi_band = si->si_band;
632 			break;
633 
634 		case LINUX_SIGCHLD:
635 			lsi->lsi_errno = 0;
636 			lsi->lsi_pid = si->si_pid;
637 			lsi->lsi_uid = si->si_uid;
638 
639 			if (si->si_code == CLD_STOPPED)
640 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
641 			else if (si->si_code == CLD_CONTINUED)
642 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
643 			else
644 				lsi->lsi_status = si->si_status;
645 			break;
646 
647 		case LINUX_SIGBUS:
648 		case LINUX_SIGILL:
649 		case LINUX_SIGFPE:
650 		case LINUX_SIGSEGV:
651 			lsi->lsi_addr = PTROUT(si->si_addr);
652 			break;
653 
654 		default:
655 			lsi->lsi_pid = si->si_pid;
656 			lsi->lsi_uid = si->si_uid;
657 			if (sig >= LINUX_SIGRTMIN) {
658 				lsi->lsi_int = si->si_value.sival_int;
659 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
660 			}
661 			break;
662 		}
663 		break;
664 	}
665 }
666 
667 void
668 lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
669 {
670 
671 	ksi->ksi_signo = sig;
672 	ksi->ksi_code = lsi->lsi_code;	/* XXX. Convert. */
673 	ksi->ksi_pid = lsi->lsi_pid;
674 	ksi->ksi_uid = lsi->lsi_uid;
675 	ksi->ksi_status = lsi->lsi_status;
676 	ksi->ksi_addr = PTRIN(lsi->lsi_addr);
677 	ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
678 }
679 
680 int
681 linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
682 {
683 	l_siginfo_t linfo;
684 	struct proc *p;
685 	ksiginfo_t ksi;
686 	int error;
687 	int sig;
688 
689 	if (!LINUX_SIG_VALID(args->sig))
690 		return (EINVAL);
691 
692 	error = copyin(args->info, &linfo, sizeof(linfo));
693 	if (error != 0)
694 		return (error);
695 
696 	if (linfo.lsi_code >= 0)
697 		return (EPERM);
698 
699 	sig = linux_to_bsd_signal(args->sig);
700 
701 	error = ESRCH;
702 	if ((p = pfind_any(args->pid)) != NULL) {
703 		error = p_cansignal(td, p, sig);
704 		if (error != 0) {
705 			PROC_UNLOCK(p);
706 			return (error);
707 		}
708 
709 		ksiginfo_init(&ksi);
710 		lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
711 		error = tdsendsignal(p, NULL, sig, &ksi);
712 		PROC_UNLOCK(p);
713 	}
714 
715 	return (error);
716 }
717 
718 int
719 linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
720 {
721 	l_siginfo_t linfo;
722 	struct thread *tds;
723 	ksiginfo_t ksi;
724 	int error;
725 	int sig;
726 
727 	if (!LINUX_SIG_VALID(args->sig))
728 		return (EINVAL);
729 
730 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
731 	if (error != 0)
732 		return (error);
733 
734 	if (linfo.lsi_code >= 0)
735 		return (EPERM);
736 
737 	tds = linux_tdfind(td, args->tid, args->tgid);
738 	if (tds == NULL)
739 		return (ESRCH);
740 
741 	sig = linux_to_bsd_signal(args->sig);
742 	ksiginfo_init(&ksi);
743 	lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
744 	return (linux_do_tkill(td, tds, &ksi));
745 }
746