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_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 static void
linux_to_bsd_sigaction(l_sigaction_t * lsa,struct sigaction * bsa)63 linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
64 {
65 unsigned long flags;
66
67 linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
68 bsa->sa_handler = PTRIN(lsa->lsa_handler);
69 bsa->sa_flags = 0;
70
71 flags = lsa->lsa_flags;
72 if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
73 flags &= ~LINUX_SA_NOCLDSTOP;
74 bsa->sa_flags |= SA_NOCLDSTOP;
75 }
76 if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
77 flags &= ~LINUX_SA_NOCLDWAIT;
78 bsa->sa_flags |= SA_NOCLDWAIT;
79 }
80 if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
81 flags &= ~LINUX_SA_SIGINFO;
82 bsa->sa_flags |= SA_SIGINFO;
83 #ifdef notyet
84 /*
85 * XXX: We seem to be missing code to convert
86 * some of the fields in ucontext_t.
87 */
88 linux_msg(curthread,
89 "partially unsupported sigaction flag SA_SIGINFO");
90 #endif
91 }
92 if (lsa->lsa_flags & LINUX_SA_RESTORER) {
93 flags &= ~LINUX_SA_RESTORER;
94 /*
95 * We ignore the lsa_restorer and always use our own signal
96 * trampoline instead. It looks like SA_RESTORER is obsolete
97 * in Linux too - it doesn't seem to be used at all on arm64.
98 * In any case: see Linux sigreturn(2).
99 */
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
bsd_to_linux_sigaction(struct sigaction * bsa,l_sigaction_t * lsa)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
linux_do_sigaction(struct thread * td,int linux_sig,l_sigaction_t * linux_nsa,l_sigaction_t * linux_osa)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
linux_signal(struct thread * td,struct linux_signal_args * args)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
linux_rt_sigaction(struct thread * td,struct linux_rt_sigaction_args * args)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
linux_do_sigprocmask(struct thread * td,int how,l_sigset_t * new,l_sigset_t * old)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
linux_sigprocmask(struct thread * td,struct linux_sigprocmask_args * args)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
linux_rt_sigprocmask(struct thread * td,struct linux_rt_sigprocmask_args * args)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
linux_sgetmask(struct thread * td,struct linux_sgetmask_args * args)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
linux_ssetmask(struct thread * td,struct linux_ssetmask_args * args)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
linux_sigpending(struct thread * td,struct linux_sigpending_args * args)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
linux_rt_sigpending(struct thread * td,struct linux_rt_sigpending_args * args)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 /*
393 * MPSAFE
394 */
395 int
linux_rt_sigtimedwait(struct thread * td,struct linux_rt_sigtimedwait_args * args)396 linux_rt_sigtimedwait(struct thread *td,
397 struct linux_rt_sigtimedwait_args *args)
398 {
399 int error, sig;
400 l_timeval ltv;
401 struct timeval tv;
402 struct timespec ts, *tsa;
403 l_sigset_t lset;
404 sigset_t bset;
405 l_siginfo_t linfo;
406 ksiginfo_t info;
407
408 if (args->sigsetsize != sizeof(l_sigset_t))
409 return (EINVAL);
410
411 if ((error = copyin(args->mask, &lset, sizeof(lset))))
412 return (error);
413 linux_to_bsd_sigset(&lset, &bset);
414
415 tsa = NULL;
416 if (args->timeout) {
417 if ((error = copyin(args->timeout, <v, sizeof(ltv))))
418 return (error);
419 tv.tv_sec = (long)ltv.tv_sec;
420 tv.tv_usec = (suseconds_t)ltv.tv_usec;
421 if (itimerfix(&tv)) {
422 /*
423 * The timeout was invalid. Convert it to something
424 * valid that will act as it does under Linux.
425 */
426 tv.tv_sec += tv.tv_usec / 1000000;
427 tv.tv_usec %= 1000000;
428 if (tv.tv_usec < 0) {
429 tv.tv_sec -= 1;
430 tv.tv_usec += 1000000;
431 }
432 if (tv.tv_sec < 0)
433 timevalclear(&tv);
434 }
435 TIMEVAL_TO_TIMESPEC(&tv, &ts);
436 tsa = &ts;
437 }
438 error = kern_sigtimedwait(td, bset, &info, tsa);
439 if (error)
440 return (error);
441
442 sig = bsd_to_linux_signal(info.ksi_signo);
443
444 if (args->ptr) {
445 memset(&linfo, 0, sizeof(linfo));
446 ksiginfo_to_lsiginfo(&info, &linfo, sig);
447 error = copyout(&linfo, args->ptr, sizeof(linfo));
448 }
449 if (error == 0)
450 td->td_retval[0] = sig;
451
452 return (error);
453 }
454
455 int
linux_kill(struct thread * td,struct linux_kill_args * args)456 linux_kill(struct thread *td, struct linux_kill_args *args)
457 {
458 int l_signum;
459
460 /*
461 * Allow signal 0 as a means to check for privileges
462 */
463 if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
464 return (EINVAL);
465
466 if (args->signum > 0)
467 l_signum = linux_to_bsd_signal(args->signum);
468 else
469 l_signum = 0;
470
471 return (kern_kill(td, args->pid, l_signum));
472 }
473
474 static int
linux_do_tkill(struct thread * td,struct thread * tdt,ksiginfo_t * ksi)475 linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
476 {
477 struct proc *p;
478 int error;
479
480 p = tdt->td_proc;
481 AUDIT_ARG_SIGNUM(ksi->ksi_signo);
482 AUDIT_ARG_PID(p->p_pid);
483 AUDIT_ARG_PROCESS(p);
484
485 error = p_cansignal(td, p, ksi->ksi_signo);
486 if (error != 0 || ksi->ksi_signo == 0)
487 goto out;
488
489 tdksignal(tdt, ksi->ksi_signo, ksi);
490
491 out:
492 PROC_UNLOCK(p);
493 return (error);
494 }
495
496 int
linux_tgkill(struct thread * td,struct linux_tgkill_args * args)497 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
498 {
499 struct thread *tdt;
500 ksiginfo_t ksi;
501 int sig;
502
503 if (args->pid <= 0 || args->tgid <=0)
504 return (EINVAL);
505
506 /*
507 * Allow signal 0 as a means to check for privileges
508 */
509 if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
510 return (EINVAL);
511
512 if (args->sig > 0)
513 sig = linux_to_bsd_signal(args->sig);
514 else
515 sig = 0;
516
517 tdt = linux_tdfind(td, args->pid, args->tgid);
518 if (tdt == NULL)
519 return (ESRCH);
520
521 ksiginfo_init(&ksi);
522 ksi.ksi_signo = sig;
523 ksi.ksi_code = SI_LWP;
524 ksi.ksi_errno = 0;
525 ksi.ksi_pid = td->td_proc->p_pid;
526 ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
527 return (linux_do_tkill(td, tdt, &ksi));
528 }
529
530 /*
531 * Deprecated since 2.5.75. Replaced by tgkill().
532 */
533 int
linux_tkill(struct thread * td,struct linux_tkill_args * args)534 linux_tkill(struct thread *td, struct linux_tkill_args *args)
535 {
536 struct thread *tdt;
537 ksiginfo_t ksi;
538 int sig;
539
540 if (args->tid <= 0)
541 return (EINVAL);
542
543 if (!LINUX_SIG_VALID(args->sig))
544 return (EINVAL);
545
546 sig = linux_to_bsd_signal(args->sig);
547
548 tdt = linux_tdfind(td, args->tid, -1);
549 if (tdt == NULL)
550 return (ESRCH);
551
552 ksiginfo_init(&ksi);
553 ksi.ksi_signo = sig;
554 ksi.ksi_code = SI_LWP;
555 ksi.ksi_errno = 0;
556 ksi.ksi_pid = td->td_proc->p_pid;
557 ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
558 return (linux_do_tkill(td, tdt, &ksi));
559 }
560
561 void
ksiginfo_to_lsiginfo(const ksiginfo_t * ksi,l_siginfo_t * lsi,l_int sig)562 ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
563 {
564
565 siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
566 }
567
568 static void
sicode_to_lsicode(int si_code,int * lsi_code)569 sicode_to_lsicode(int si_code, int *lsi_code)
570 {
571
572 switch (si_code) {
573 case SI_USER:
574 *lsi_code = LINUX_SI_USER;
575 break;
576 case SI_KERNEL:
577 *lsi_code = LINUX_SI_KERNEL;
578 break;
579 case SI_QUEUE:
580 *lsi_code = LINUX_SI_QUEUE;
581 break;
582 case SI_TIMER:
583 *lsi_code = LINUX_SI_TIMER;
584 break;
585 case SI_MESGQ:
586 *lsi_code = LINUX_SI_MESGQ;
587 break;
588 case SI_ASYNCIO:
589 *lsi_code = LINUX_SI_ASYNCIO;
590 break;
591 case SI_LWP:
592 *lsi_code = LINUX_SI_TKILL;
593 break;
594 default:
595 *lsi_code = si_code;
596 break;
597 }
598 }
599
600 void
siginfo_to_lsiginfo(const siginfo_t * si,l_siginfo_t * lsi,l_int sig)601 siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
602 {
603
604 /* sig alredy converted */
605 lsi->lsi_signo = sig;
606 sicode_to_lsicode(si->si_code, &lsi->lsi_code);
607
608 switch (si->si_code) {
609 case SI_LWP:
610 lsi->lsi_pid = si->si_pid;
611 lsi->lsi_uid = si->si_uid;
612 break;
613
614 case SI_TIMER:
615 lsi->lsi_int = si->si_value.sival_int;
616 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
617 lsi->lsi_tid = si->si_timerid;
618 break;
619
620 case SI_QUEUE:
621 lsi->lsi_pid = si->si_pid;
622 lsi->lsi_uid = si->si_uid;
623 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
624 break;
625
626 case SI_ASYNCIO:
627 lsi->lsi_int = si->si_value.sival_int;
628 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
629 break;
630
631 default:
632 switch (sig) {
633 case LINUX_SIGPOLL:
634 /* XXX si_fd? */
635 lsi->lsi_band = si->si_band;
636 break;
637
638 case LINUX_SIGCHLD:
639 lsi->lsi_errno = 0;
640 lsi->lsi_pid = si->si_pid;
641 lsi->lsi_uid = si->si_uid;
642
643 if (si->si_code == CLD_STOPPED || si->si_code == CLD_KILLED)
644 lsi->lsi_status = bsd_to_linux_signal(si->si_status);
645 else if (si->si_code == CLD_CONTINUED)
646 lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
647 else
648 lsi->lsi_status = si->si_status;
649 break;
650
651 case LINUX_SIGBUS:
652 case LINUX_SIGILL:
653 case LINUX_SIGFPE:
654 case LINUX_SIGSEGV:
655 lsi->lsi_addr = PTROUT(si->si_addr);
656 break;
657
658 default:
659 lsi->lsi_pid = si->si_pid;
660 lsi->lsi_uid = si->si_uid;
661 if (sig >= LINUX_SIGRTMIN) {
662 lsi->lsi_int = si->si_value.sival_int;
663 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
664 }
665 break;
666 }
667 break;
668 }
669 }
670
671 void
lsiginfo_to_ksiginfo(const l_siginfo_t * lsi,ksiginfo_t * ksi,int sig)672 lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
673 {
674
675 ksi->ksi_signo = sig;
676 ksi->ksi_code = lsi->lsi_code; /* XXX. Convert. */
677 ksi->ksi_pid = lsi->lsi_pid;
678 ksi->ksi_uid = lsi->lsi_uid;
679 ksi->ksi_status = lsi->lsi_status;
680 ksi->ksi_addr = PTRIN(lsi->lsi_addr);
681 ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
682 }
683
684 int
linux_rt_sigqueueinfo(struct thread * td,struct linux_rt_sigqueueinfo_args * args)685 linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
686 {
687 l_siginfo_t linfo;
688 struct proc *p;
689 ksiginfo_t ksi;
690 int error;
691 int sig;
692
693 if (!LINUX_SIG_VALID(args->sig))
694 return (EINVAL);
695
696 error = copyin(args->info, &linfo, sizeof(linfo));
697 if (error != 0)
698 return (error);
699
700 if (linfo.lsi_code >= 0)
701 return (EPERM);
702
703 sig = linux_to_bsd_signal(args->sig);
704
705 error = ESRCH;
706 if ((p = pfind_any(args->pid)) != NULL) {
707 error = p_cansignal(td, p, sig);
708 if (error != 0) {
709 PROC_UNLOCK(p);
710 return (error);
711 }
712
713 ksiginfo_init(&ksi);
714 lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
715 error = tdsendsignal(p, NULL, sig, &ksi);
716 PROC_UNLOCK(p);
717 }
718
719 return (error);
720 }
721
722 int
linux_rt_tgsigqueueinfo(struct thread * td,struct linux_rt_tgsigqueueinfo_args * args)723 linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
724 {
725 l_siginfo_t linfo;
726 struct thread *tds;
727 ksiginfo_t ksi;
728 int error;
729 int sig;
730
731 if (!LINUX_SIG_VALID(args->sig))
732 return (EINVAL);
733
734 error = copyin(args->uinfo, &linfo, sizeof(linfo));
735 if (error != 0)
736 return (error);
737
738 if (linfo.lsi_code >= 0)
739 return (EPERM);
740
741 tds = linux_tdfind(td, args->tid, args->tgid);
742 if (tds == NULL)
743 return (ESRCH);
744
745 sig = linux_to_bsd_signal(args->sig);
746 ksiginfo_init(&ksi);
747 lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
748 return (linux_do_tkill(td, tds, &ksi));
749 }
750
751 int
linux_rt_sigsuspend(struct thread * td,struct linux_rt_sigsuspend_args * uap)752 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
753 {
754 l_sigset_t lmask;
755 sigset_t sigmask;
756 int error;
757
758 if (uap->sigsetsize != sizeof(l_sigset_t))
759 return (EINVAL);
760
761 error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
762 if (error != 0)
763 return (error);
764
765 linux_to_bsd_sigset(&lmask, &sigmask);
766 return (kern_sigsuspend(td, sigmask));
767 }
768