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