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