linux_signal.c revision 1.48.6.1 1 /* $NetBSD: linux_signal.c,v 1.48.6.1 2005/11/29 21:23:05 yamt Exp $ */
2 /*-
3 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Frank van der Linden and Eric Haszlakiewicz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37 /*
38 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
39 */
40
41 /*
42 * Functions in multiarch:
43 * linux_sys_signal : linux_sig_notalpha.c
44 * linux_sys_siggetmask : linux_sig_notalpha.c
45 * linux_sys_sigsetmask : linux_sig_notalpha.c
46 * linux_sys_pause : linux_sig_notalpha.c
47 * linux_sys_sigaction : linux_sigaction.c
48 *
49 */
50
51 /*
52 * Unimplemented:
53 * linux_sys_rt_sigtimedwait : sigsuspend w/timeout.
54 */
55
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.48.6.1 2005/11/29 21:23:05 yamt Exp $");
58
59 #define COMPAT_LINUX 1
60
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/namei.h>
64 #include <sys/proc.h>
65 #include <sys/filedesc.h>
66 #include <sys/ioctl.h>
67 #include <sys/mount.h>
68 #include <sys/kernel.h>
69 #include <sys/signal.h>
70 #include <sys/signalvar.h>
71 #include <sys/malloc.h>
72
73 #include <sys/sa.h>
74 #include <sys/syscallargs.h>
75
76 #include <compat/linux/common/linux_types.h>
77 #include <compat/linux/common/linux_signal.h>
78 #include <compat/linux/common/linux_exec.h> /* For emul_linux */
79 #include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */
80 #include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */
81 #include <compat/linux/common/linux_siginfo.h>
82 #include <compat/linux/common/linux_sigevent.h>
83 #include <compat/linux/common/linux_util.h>
84
85 #include <compat/linux/linux_syscallargs.h>
86
87 /* Locally used defines (in bsd<->linux conversion functions): */
88 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s)))
89 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
90 & (1 << ((n) - 1) % LINUX__NSIG_BPW))
91 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
92 |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
93
94 #ifdef DEBUG_LINUX
95 #define DPRINTF(a) uprintf a
96 #else
97 #define DPRINTF(a)
98 #endif
99
100 extern const int native_to_linux_signo[];
101 extern const int linux_to_native_signo[];
102
103 /*
104 * Convert between Linux and BSD signal sets.
105 */
106 #if LINUX__NSIG_WORDS > 1
107 void
108 linux_old_extra_to_native_sigset(bss, lss, extra)
109 sigset_t *bss;
110 const linux_old_sigset_t *lss;
111 const unsigned long *extra;
112 {
113 linux_sigset_t lsnew;
114
115 /* convert old sigset to new sigset */
116 linux_sigemptyset(&lsnew);
117 lsnew.sig[0] = *lss;
118 if (extra)
119 memcpy(&lsnew.sig[1], extra,
120 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
121
122 linux_to_native_sigset(bss, &lsnew);
123 }
124
125 void
126 native_to_linux_old_extra_sigset(lss, extra, bss)
127 linux_old_sigset_t *lss;
128 unsigned long *extra;
129 const sigset_t *bss;
130 {
131 linux_sigset_t lsnew;
132
133 native_to_linux_sigset(&lsnew, bss);
134
135 /* convert new sigset to old sigset */
136 *lss = lsnew.sig[0];
137 if (extra)
138 memcpy(extra, &lsnew.sig[1],
139 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
140 }
141 #endif /* LINUX__NSIG_WORDS > 1 */
142
143 void
144 linux_to_native_sigset(bss, lss)
145 sigset_t *bss;
146 const linux_sigset_t *lss;
147 {
148 int i, newsig;
149
150 sigemptyset(bss);
151 for (i = 1; i < LINUX__NSIG; i++) {
152 if (linux_sigismember(lss, i)) {
153 newsig = linux_to_native_signo[i];
154 if (newsig)
155 sigaddset(bss, newsig);
156 }
157 }
158 }
159
160 void
161 native_to_linux_sigset(lss, bss)
162 linux_sigset_t *lss;
163 const sigset_t *bss;
164 {
165 int i, newsig;
166
167 linux_sigemptyset(lss);
168 for (i = 1; i < NSIG; i++) {
169 if (sigismember(bss, i)) {
170 newsig = native_to_linux_signo[i];
171 if (newsig)
172 linux_sigaddset(lss, newsig);
173 }
174 }
175 }
176
177 unsigned int
178 native_to_linux_sigflags(bsf)
179 const int bsf;
180 {
181 unsigned int lsf = 0;
182 if ((bsf & SA_NOCLDSTOP) != 0)
183 lsf |= LINUX_SA_NOCLDSTOP;
184 if ((bsf & SA_NOCLDWAIT) != 0)
185 lsf |= LINUX_SA_NOCLDWAIT;
186 if ((bsf & SA_ONSTACK) != 0)
187 lsf |= LINUX_SA_ONSTACK;
188 if ((bsf & SA_RESTART) != 0)
189 lsf |= LINUX_SA_RESTART;
190 if ((bsf & SA_NODEFER) != 0)
191 lsf |= LINUX_SA_NOMASK;
192 if ((bsf & SA_RESETHAND) != 0)
193 lsf |= LINUX_SA_ONESHOT;
194 if ((bsf & SA_SIGINFO) != 0)
195 lsf |= LINUX_SA_SIGINFO;
196 return lsf;
197 }
198
199 int
200 linux_to_native_sigflags(lsf)
201 const unsigned long lsf;
202 {
203 int bsf = 0;
204 if ((lsf & LINUX_SA_NOCLDSTOP) != 0)
205 bsf |= SA_NOCLDSTOP;
206 if ((lsf & LINUX_SA_NOCLDWAIT) != 0)
207 bsf |= SA_NOCLDWAIT;
208 if ((lsf & LINUX_SA_ONSTACK) != 0)
209 bsf |= SA_ONSTACK;
210 if ((lsf & LINUX_SA_RESTART) != 0)
211 bsf |= SA_RESTART;
212 if ((lsf & LINUX_SA_ONESHOT) != 0)
213 bsf |= SA_RESETHAND;
214 if ((lsf & LINUX_SA_NOMASK) != 0)
215 bsf |= SA_NODEFER;
216 if ((lsf & LINUX_SA_SIGINFO) != 0)
217 bsf |= SA_SIGINFO;
218 if ((lsf & ~LINUX_SA_ALLBITS) != 0)
219 DPRINTF(("linux_old_to_native_sigflags: "
220 "%lx extra bits ignored\n", lsf));
221 return bsf;
222 }
223
224 /*
225 * Convert between Linux and BSD sigaction structures.
226 */
227 void
228 linux_old_to_native_sigaction(bsa, lsa)
229 struct sigaction *bsa;
230 const struct linux_old_sigaction *lsa;
231 {
232 bsa->sa_handler = lsa->linux_sa_handler;
233 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
234 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags);
235 }
236
237 void
238 native_to_linux_old_sigaction(lsa, bsa)
239 struct linux_old_sigaction *lsa;
240 const struct sigaction *bsa;
241 {
242 lsa->linux_sa_handler = bsa->sa_handler;
243 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
244 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags);
245 #ifndef __alpha__
246 lsa->linux_sa_restorer = NULL;
247 #endif
248 }
249
250 /* ...and the new sigaction conversion funcs. */
251 void
252 linux_to_native_sigaction(bsa, lsa)
253 struct sigaction *bsa;
254 const struct linux_sigaction *lsa;
255 {
256 bsa->sa_handler = lsa->linux_sa_handler;
257 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
258 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags);
259 }
260
261 void
262 native_to_linux_sigaction(lsa, bsa)
263 struct linux_sigaction *lsa;
264 const struct sigaction *bsa;
265 {
266 lsa->linux_sa_handler = bsa->sa_handler;
267 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
268 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags);
269 #ifndef __alpha__
270 lsa->linux_sa_restorer = NULL;
271 #endif
272 }
273
274 /* ----------------------------------------------------------------------- */
275
276 /*
277 * The Linux sigaction() system call. Do the usual conversions,
278 * and just call sigaction(). Some flags and values are silently
279 * ignored (see above).
280 */
281 int
282 linux_sys_rt_sigaction(l, v, retval)
283 struct lwp *l;
284 void *v;
285 register_t *retval;
286 {
287 struct linux_sys_rt_sigaction_args /* {
288 syscallarg(int) signum;
289 syscallarg(const struct linux_sigaction *) nsa;
290 syscallarg(struct linux_sigaction *) osa;
291 syscallarg(size_t) sigsetsize;
292 } */ *uap = v;
293 struct proc *p = l->l_proc;
294 struct linux_sigaction nlsa, olsa;
295 struct sigaction nbsa, obsa;
296 int error, sig;
297 void *tramp = NULL;
298 int vers = 0;
299 #if defined __amd64__
300 struct sigacts *ps = p->p_sigacts;
301 #endif
302
303 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
304 return (EINVAL);
305
306 if (SCARG(uap, nsa)) {
307 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
308 if (error)
309 return (error);
310 linux_to_native_sigaction(&nbsa, &nlsa);
311 }
312
313 sig = SCARG(uap, signum);
314 if (sig < 0 || sig >= LINUX__NSIG)
315 return (EINVAL);
316 if (sig > 0 && !linux_to_native_signo[sig]) {
317 /* Pretend that we did something useful for unknown signals. */
318 obsa.sa_handler = SIG_IGN;
319 sigemptyset(&obsa.sa_mask);
320 obsa.sa_flags = 0;
321 } else {
322 #if defined __amd64__
323 if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) {
324 if ((tramp = nlsa.linux_sa_restorer) != NULL)
325 vers = 2; /* XXX arch dependant */
326 }
327 #endif
328
329 error = sigaction1(p, linux_to_native_signo[sig],
330 SCARG(uap, nsa) ? &nbsa : NULL,
331 SCARG(uap, osa) ? &obsa : NULL,
332 tramp, vers);
333 if (error)
334 return (error);
335 }
336 if (SCARG(uap, osa)) {
337 native_to_linux_sigaction(&olsa, &obsa);
338
339 #if defined __amd64__
340 if (ps->sa_sigdesc[sig].sd_vers != 0) {
341 olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp;
342 olsa.linux_sa_flags |= LINUX_SA_RESTORER;
343 }
344 #endif
345
346 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
347 if (error)
348 return (error);
349 }
350 return (0);
351 }
352
353 int
354 linux_sigprocmask1(p, how, set, oset)
355 struct proc *p;
356 int how;
357 const linux_old_sigset_t *set;
358 linux_old_sigset_t *oset;
359 {
360 linux_old_sigset_t nlss, olss;
361 sigset_t nbss, obss;
362 int error;
363
364 switch (how) {
365 case LINUX_SIG_BLOCK:
366 how = SIG_BLOCK;
367 break;
368 case LINUX_SIG_UNBLOCK:
369 how = SIG_UNBLOCK;
370 break;
371 case LINUX_SIG_SETMASK:
372 how = SIG_SETMASK;
373 break;
374 default:
375 return (EINVAL);
376 }
377
378 if (set) {
379 error = copyin(set, &nlss, sizeof(nlss));
380 if (error)
381 return (error);
382 linux_old_to_native_sigset(&nbss, &nlss);
383 }
384 error = sigprocmask1(p, how,
385 set ? &nbss : NULL, oset ? &obss : NULL);
386 if (error)
387 return (error);
388 if (oset) {
389 native_to_linux_old_sigset(&olss, &obss);
390 error = copyout(&olss, oset, sizeof(olss));
391 if (error)
392 return (error);
393 }
394 return (error);
395 }
396
397 int
398 linux_sys_rt_sigprocmask(l, v, retval)
399 struct lwp *l;
400 void *v;
401 register_t *retval;
402 {
403 struct linux_sys_rt_sigprocmask_args /* {
404 syscallarg(int) how;
405 syscallarg(const linux_sigset_t *) set;
406 syscallarg(linux_sigset_t *) oset;
407 syscallarg(size_t) sigsetsize;
408 } */ *uap = v;
409 struct proc *p = l->l_proc;
410 linux_sigset_t nlss, olss, *oset;
411 const linux_sigset_t *set;
412 sigset_t nbss, obss;
413 int error, how;
414
415 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
416 return (EINVAL);
417
418 switch (SCARG(uap, how)) {
419 case LINUX_SIG_BLOCK:
420 how = SIG_BLOCK;
421 break;
422 case LINUX_SIG_UNBLOCK:
423 how = SIG_UNBLOCK;
424 break;
425 case LINUX_SIG_SETMASK:
426 how = SIG_SETMASK;
427 break;
428 default:
429 return (EINVAL);
430 }
431
432 set = SCARG(uap, set);
433 oset = SCARG(uap, oset);
434
435 if (set) {
436 error = copyin(set, &nlss, sizeof(nlss));
437 if (error)
438 return (error);
439 linux_to_native_sigset(&nbss, &nlss);
440 }
441 error = sigprocmask1(p, how,
442 set ? &nbss : NULL, oset ? &obss : NULL);
443 if (!error && oset) {
444 native_to_linux_sigset(&olss, &obss);
445 error = copyout(&olss, oset, sizeof(olss));
446 }
447 return (error);
448 }
449
450 int
451 linux_sys_rt_sigpending(l, v, retval)
452 struct lwp *l;
453 void *v;
454 register_t *retval;
455 {
456 struct linux_sys_rt_sigpending_args /* {
457 syscallarg(linux_sigset_t *) set;
458 syscallarg(size_t) sigsetsize;
459 } */ *uap = v;
460 struct proc *p = l->l_proc;
461 sigset_t bss;
462 linux_sigset_t lss;
463
464 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
465 return (EINVAL);
466
467 sigpending1(p, &bss);
468 native_to_linux_sigset(&lss, &bss);
469 return copyout(&lss, SCARG(uap, set), sizeof(lss));
470 }
471
472 #ifndef __amd64__
473 int
474 linux_sys_sigpending(l, v, retval)
475 struct lwp *l;
476 void *v;
477 register_t *retval;
478 {
479 struct linux_sys_sigpending_args /* {
480 syscallarg(linux_old_sigset_t *) mask;
481 } */ *uap = v;
482 struct proc *p = l->l_proc;
483 sigset_t bss;
484 linux_old_sigset_t lss;
485
486 sigpending1(p, &bss);
487 native_to_linux_old_sigset(&lss, &bss);
488 return copyout(&lss, SCARG(uap, set), sizeof(lss));
489 }
490
491 int
492 linux_sys_sigsuspend(l, v, retval)
493 struct lwp *l;
494 void *v;
495 register_t *retval;
496 {
497 struct linux_sys_sigsuspend_args /* {
498 syscallarg(caddr_t) restart;
499 syscallarg(int) oldmask;
500 syscallarg(int) mask;
501 } */ *uap = v;
502 struct proc *p = l->l_proc;
503 linux_old_sigset_t lss;
504 sigset_t bss;
505
506 lss = SCARG(uap, mask);
507 linux_old_to_native_sigset(&bss, &lss);
508 return (sigsuspend1(p, &bss));
509 }
510 #endif /* __amd64__ */
511
512 int
513 linux_sys_rt_sigsuspend(l, v, retval)
514 struct lwp *l;
515 void *v;
516 register_t *retval;
517 {
518 struct linux_sys_rt_sigsuspend_args /* {
519 syscallarg(linux_sigset_t *) unewset;
520 syscallarg(size_t) sigsetsize;
521 } */ *uap = v;
522 struct proc *p = l->l_proc;
523 linux_sigset_t lss;
524 sigset_t bss;
525 int error;
526
527 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
528 return (EINVAL);
529
530 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t));
531 if (error)
532 return (error);
533
534 linux_to_native_sigset(&bss, &lss);
535
536 return (sigsuspend1(p, &bss));
537 }
538
539 /*
540 * Once more: only a signal conversion is needed.
541 * Note: also used as sys_rt_queueinfo. The info field is ignored.
542 */
543 int
544 linux_sys_rt_queueinfo(l, v, retval)
545 struct lwp *l;
546 void *v;
547 register_t *retval;
548 {
549 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */
550 #if 0
551 struct linux_sys_rt_queueinfo_args /* {
552 syscallarg(int) pid;
553 syscallarg(int) signum;
554 syscallarg(siginfo_t *) uinfo;
555 } */ *uap = v;
556 #endif
557
558 /* XXX To really implement this we need to */
559 /* XXX keep a list of queued signals somewhere. */
560 return (linux_sys_kill(l, v, retval));
561 }
562
563 int
564 linux_sys_kill(l, v, retval)
565 struct lwp *l;
566 void *v;
567 register_t *retval;
568 {
569 struct linux_sys_kill_args /* {
570 syscallarg(int) pid;
571 syscallarg(int) signum;
572 } */ *uap = v;
573
574 struct sys_kill_args ka;
575 int sig;
576
577 SCARG(&ka, pid) = SCARG(uap, pid);
578 sig = SCARG(uap, signum);
579 if (sig < 0 || sig >= LINUX__NSIG)
580 return (EINVAL);
581 SCARG(&ka, signum) = linux_to_native_signo[sig];
582 return sys_kill(l, &ka, retval);
583 }
584
585 #ifdef LINUX_SS_ONSTACK
586 static void linux_to_native_sigaltstack __P((struct sigaltstack *,
587 const struct linux_sigaltstack *));
588
589 static void
590 linux_to_native_sigaltstack(bss, lss)
591 struct sigaltstack *bss;
592 const struct linux_sigaltstack *lss;
593 {
594 bss->ss_sp = lss->ss_sp;
595 bss->ss_size = lss->ss_size;
596 if (lss->ss_flags & LINUX_SS_ONSTACK)
597 bss->ss_flags = SS_ONSTACK;
598 else if (lss->ss_flags & LINUX_SS_DISABLE)
599 bss->ss_flags = SS_DISABLE;
600 else
601 bss->ss_flags = 0;
602 }
603
604 void
605 native_to_linux_sigaltstack(lss, bss)
606 struct linux_sigaltstack *lss;
607 const struct sigaltstack *bss;
608 {
609 lss->ss_sp = bss->ss_sp;
610 lss->ss_size = bss->ss_size;
611 if (bss->ss_flags & SS_ONSTACK)
612 lss->ss_flags = LINUX_SS_ONSTACK;
613 else if (bss->ss_flags & SS_DISABLE)
614 lss->ss_flags = LINUX_SS_DISABLE;
615 else
616 lss->ss_flags = 0;
617 }
618
619 int
620 linux_sys_sigaltstack(l, v, retval)
621 struct lwp *l;
622 void *v;
623 register_t *retval;
624 {
625 struct linux_sys_sigaltstack_args /* {
626 syscallarg(const struct linux_sigaltstack *) ss;
627 syscallarg(struct linux_sigaltstack *) oss;
628 } */ *uap = v;
629 struct proc *p = l->l_proc;
630 struct linux_sigaltstack ss;
631 struct sigaltstack nss;
632 int error;
633
634 if (SCARG(uap, oss)) {
635 native_to_linux_sigaltstack(&ss, &p->p_sigctx.ps_sigstk);
636 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0)
637 return error;
638 }
639
640 if (SCARG(uap, ss) != NULL) {
641 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0)
642 return error;
643 linux_to_native_sigaltstack(&nss, &ss);
644
645 if (nss.ss_flags & ~SS_ALLBITS)
646 return EINVAL;
647
648 if (nss.ss_flags & SS_DISABLE) {
649 if (p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK)
650 return EINVAL;
651 } else {
652 if (nss.ss_size < LINUX_MINSIGSTKSZ)
653 return ENOMEM;
654 }
655 p->p_sigctx.ps_sigstk = nss;
656 }
657
658 return 0;
659 }
660 #endif /* LINUX_SS_ONSTACK */
661
662 #ifdef LINUX_NPTL
663 int
664 linux_sys_tkill(l, v, retval)
665 struct lwp *l;
666 void *v;
667 register_t *retval;
668 {
669 struct linux_sys_tkill_args /* {
670 syscallarg(int) tid;
671 syscallarg(int) sig;
672 } */ *uap = v;
673 struct linux_sys_kill_args cup;
674
675 /* We use the PID as the TID ... */
676 SCARG(&cup, pid) = SCARG(uap, tid);
677 SCARG(&cup, signum) = SCARG(uap, sig);
678
679 return linux_sys_kill(l, &cup, retval);
680 }
681
682 int
683 linux_sys_tgkill(l, v, retval)
684 struct lwp *l;
685 void *v;
686 register_t *retval;
687 {
688 struct linux_sys_tgkill_args /* {
689 syscallarg(int) tgid;
690 syscallarg(int) tid;
691 syscallarg(int) sig;
692 } */ *uap = v;
693 struct linux_sys_kill_args cup;
694 struct linux_emuldata *led;
695 struct proc *p;
696
697 SCARG(&cup, pid) = SCARG(uap, tid);
698 SCARG(&cup, signum) = SCARG(uap, sig);
699
700 if (SCARG(uap, tgid) == -1)
701 return linux_sys_kill(l, &cup, retval);
702
703 /* We use the PID as the TID, but make sure the group ID is right */
704 if ((p = pfind(SCARG(uap, tid))) == NULL)
705 return ESRCH;
706
707 if (p->p_emul != &emul_linux)
708 return ESRCH;
709
710 led = p->p_emuldata;
711
712 if (led->s->group_pid != SCARG(uap, tgid))
713 return ESRCH;
714
715 return linux_sys_kill(l, &cup, retval);
716 }
717 #endif /* LINUX_NPTL */
718