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