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