linux_signal.c revision 293498
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: stable/10/sys/compat/linux/linux_signal.c 293498 2016-01-09 15:21:45Z dchagin $");
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
58static int	linux_do_tkill(struct thread *td, struct thread *tdt,
59		    ksiginfo_t *ksi);
60static void	sicode_to_lsicode(int si_code, int *lsi_code);
61
62
63void
64linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
65{
66	int b, l;
67
68	SIGEMPTYSET(*bss);
69	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
70	bss->__bits[1] = lss->__bits[1];
71	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
72		if (LINUX_SIGISMEMBER(*lss, l)) {
73			b = linux_to_bsd_signal[_SIG_IDX(l)];
74			if (b)
75				SIGADDSET(*bss, b);
76		}
77	}
78}
79
80void
81bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
82{
83	int b, l;
84
85	LINUX_SIGEMPTYSET(*lss);
86	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
87	lss->__bits[1] = bss->__bits[1];
88	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
89		if (SIGISMEMBER(*bss, b)) {
90			l = bsd_to_linux_signal[_SIG_IDX(b)];
91			if (l)
92				LINUX_SIGADDSET(*lss, l);
93		}
94	}
95}
96
97static void
98linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
99{
100
101	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
102	bsa->sa_handler = PTRIN(lsa->lsa_handler);
103	bsa->sa_flags = 0;
104	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
105		bsa->sa_flags |= SA_NOCLDSTOP;
106	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
107		bsa->sa_flags |= SA_NOCLDWAIT;
108	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
109		bsa->sa_flags |= SA_SIGINFO;
110	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
111		bsa->sa_flags |= SA_ONSTACK;
112	if (lsa->lsa_flags & LINUX_SA_RESTART)
113		bsa->sa_flags |= SA_RESTART;
114	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
115		bsa->sa_flags |= SA_RESETHAND;
116	if (lsa->lsa_flags & LINUX_SA_NOMASK)
117		bsa->sa_flags |= SA_NODEFER;
118}
119
120static void
121bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
122{
123
124	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
125#ifdef COMPAT_LINUX32
126	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
127#else
128	lsa->lsa_handler = bsa->sa_handler;
129#endif
130	lsa->lsa_restorer = 0;		/* unsupported */
131	lsa->lsa_flags = 0;
132	if (bsa->sa_flags & SA_NOCLDSTOP)
133		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
134	if (bsa->sa_flags & SA_NOCLDWAIT)
135		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
136	if (bsa->sa_flags & SA_SIGINFO)
137		lsa->lsa_flags |= LINUX_SA_SIGINFO;
138	if (bsa->sa_flags & SA_ONSTACK)
139		lsa->lsa_flags |= LINUX_SA_ONSTACK;
140	if (bsa->sa_flags & SA_RESTART)
141		lsa->lsa_flags |= LINUX_SA_RESTART;
142	if (bsa->sa_flags & SA_RESETHAND)
143		lsa->lsa_flags |= LINUX_SA_ONESHOT;
144	if (bsa->sa_flags & SA_NODEFER)
145		lsa->lsa_flags |= LINUX_SA_NOMASK;
146}
147
148int
149linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
150		   l_sigaction_t *linux_osa)
151{
152	struct sigaction act, oact, *nsa, *osa;
153	int error, sig;
154
155	if (!LINUX_SIG_VALID(linux_sig))
156		return (EINVAL);
157
158	osa = (linux_osa != NULL) ? &oact : NULL;
159	if (linux_nsa != NULL) {
160		nsa = &act;
161		linux_to_bsd_sigaction(linux_nsa, nsa);
162	} else
163		nsa = NULL;
164
165	if (linux_sig <= LINUX_SIGTBLSZ)
166		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
167	else
168		sig = linux_sig;
169
170	error = kern_sigaction(td, sig, nsa, osa, 0);
171	if (error)
172		return (error);
173
174	if (linux_osa != NULL)
175		bsd_to_linux_sigaction(osa, linux_osa);
176
177	return (0);
178}
179
180
181int
182linux_signal(struct thread *td, struct linux_signal_args *args)
183{
184	l_sigaction_t nsa, osa;
185	int error;
186
187#ifdef DEBUG
188	if (ldebug(signal))
189		printf(ARGS(signal, "%d, %p"),
190		    args->sig, (void *)(uintptr_t)args->handler);
191#endif
192
193	nsa.lsa_handler = args->handler;
194	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
195	LINUX_SIGEMPTYSET(nsa.lsa_mask);
196
197	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
198	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
199
200	return (error);
201}
202
203int
204linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
205{
206	l_sigaction_t nsa, osa;
207	int error;
208
209#ifdef DEBUG
210	if (ldebug(rt_sigaction))
211		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
212		    (long)args->sig, (void *)args->act,
213		    (void *)args->oact, (long)args->sigsetsize);
214#endif
215
216	if (args->sigsetsize != sizeof(l_sigset_t))
217		return (EINVAL);
218
219	if (args->act != NULL) {
220		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
221		if (error)
222			return (error);
223	}
224
225	error = linux_do_sigaction(td, args->sig,
226				   args->act ? &nsa : NULL,
227				   args->oact ? &osa : NULL);
228
229	if (args->oact != NULL && !error) {
230		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
231	}
232
233	return (error);
234}
235
236static int
237linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
238		     l_sigset_t *old)
239{
240	sigset_t omask, nmask;
241	sigset_t *nmaskp;
242	int error;
243
244	td->td_retval[0] = 0;
245
246	switch (how) {
247	case LINUX_SIG_BLOCK:
248		how = SIG_BLOCK;
249		break;
250	case LINUX_SIG_UNBLOCK:
251		how = SIG_UNBLOCK;
252		break;
253	case LINUX_SIG_SETMASK:
254		how = SIG_SETMASK;
255		break;
256	default:
257		return (EINVAL);
258	}
259	if (new != NULL) {
260		linux_to_bsd_sigset(new, &nmask);
261		nmaskp = &nmask;
262	} else
263		nmaskp = NULL;
264	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
265	if (error == 0 && old != NULL)
266		bsd_to_linux_sigset(&omask, old);
267
268	return (error);
269}
270
271int
272linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
273{
274	l_osigset_t mask;
275	l_sigset_t set, oset;
276	int error;
277
278#ifdef DEBUG
279	if (ldebug(sigprocmask))
280		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
281#endif
282
283	if (args->mask != NULL) {
284		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
285		if (error)
286			return (error);
287		LINUX_SIGEMPTYSET(set);
288		set.__bits[0] = mask;
289	}
290
291	error = linux_do_sigprocmask(td, args->how,
292				     args->mask ? &set : NULL,
293				     args->omask ? &oset : NULL);
294
295	if (args->omask != NULL && !error) {
296		mask = oset.__bits[0];
297		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
298	}
299
300	return (error);
301}
302
303int
304linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
305{
306	l_sigset_t set, oset;
307	int error;
308
309#ifdef DEBUG
310	if (ldebug(rt_sigprocmask))
311		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
312		    args->how, (void *)args->mask,
313		    (void *)args->omask, (long)args->sigsetsize);
314#endif
315
316	if (args->sigsetsize != sizeof(l_sigset_t))
317		return EINVAL;
318
319	if (args->mask != NULL) {
320		error = copyin(args->mask, &set, sizeof(l_sigset_t));
321		if (error)
322			return (error);
323	}
324
325	error = linux_do_sigprocmask(td, args->how,
326				     args->mask ? &set : NULL,
327				     args->omask ? &oset : NULL);
328
329	if (args->omask != NULL && !error) {
330		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
331	}
332
333	return (error);
334}
335
336int
337linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
338{
339	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