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