linux_signal.c revision 293540
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: stable/10/sys/compat/linux/linux_signal.c 293540 2016-01-09 16:29:51Z dchagin $"); 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 58static int linux_do_tkill(struct thread *td, struct thread *tdt, 59 ksiginfo_t *ksi); 60static void sicode_to_lsicode(int si_code, int *lsi_code); 61 62 63#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 64void 65linux_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 81void 82bsd_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 99static void 100linux_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 122static void 123bsd_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 150int 151linux_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)) 183int 184linux_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 206int 207linux_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 239static int 240linux_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)) 275int 276linux_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 308int 309linux_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)) 342int 343linux_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 360int 361linux_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 385int 386linux_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 */ 412int 413linux_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 */ 440int 441linux_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, <v, 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 521int 522linux_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 549static int 550linux_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 566out: 567 PROC_UNLOCK(p); 568 return (error); 569} 570 571int 572linux_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 */ 614int 615linux_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 632 sig = BSD_TO_LINUX_SIGNAL(args->sig); 633 634 tdt = linux_tdfind(td, args->tid, -1); 635 if (tdt == NULL) 636 return (ESRCH); 637 638 ksiginfo_init(&ksi); 639 ksi.ksi_signo = sig; 640 ksi.ksi_code = SI_LWP; 641 ksi.ksi_errno = 0; 642 ksi.ksi_pid = td->td_proc->p_pid; 643 ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid; 644 return (linux_do_tkill(td, tdt, &ksi)); 645} 646 647void 648ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig) 649{ 650 651 siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig); 652} 653 654static void 655sicode_to_lsicode(int si_code, int *lsi_code) 656{ 657 658 switch (si_code) { 659 case SI_USER: 660 *lsi_code = LINUX_SI_USER; 661 break; 662 case SI_KERNEL: 663 *lsi_code = LINUX_SI_KERNEL; 664 break; 665 case SI_QUEUE: 666 *lsi_code = LINUX_SI_QUEUE; 667 break; 668 case SI_TIMER: 669 *lsi_code = LINUX_SI_TIMER; 670 break; 671 case SI_MESGQ: 672 *lsi_code = LINUX_SI_MESGQ; 673 break; 674 case SI_ASYNCIO: 675 *lsi_code = LINUX_SI_ASYNCIO; 676 break; 677 case SI_LWP: 678 *lsi_code = LINUX_SI_TKILL; 679 break; 680 default: 681 *lsi_code = si_code; 682 break; 683 } 684} 685 686void 687siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig) 688{ 689 690 /* sig alredy converted */ 691 lsi->lsi_signo = sig; 692 sicode_to_lsicode(si->si_code, &lsi->lsi_code); 693 694 switch (si->si_code) { 695 case SI_LWP: 696 lsi->lsi_pid = si->si_pid; 697 lsi->lsi_uid = si->si_uid; 698 break; 699 700 case SI_TIMER: 701 lsi->lsi_int = si->si_value.sival_int; 702 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr); 703 lsi->lsi_tid = si->si_timerid; 704 break; 705 706 case SI_QUEUE: 707 lsi->lsi_pid = si->si_pid; 708 lsi->lsi_uid = si->si_uid; 709 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr); 710 break; 711 712 case SI_ASYNCIO: 713 lsi->lsi_int = si->si_value.sival_int; 714 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr); 715 break; 716 717 default: 718 switch (sig) { 719 case LINUX_SIGPOLL: 720 /* XXX si_fd? */ 721 lsi->lsi_band = si->si_band; 722 break; 723 724 case LINUX_SIGCHLD: 725 lsi->lsi_errno = 0; 726 lsi->lsi_pid = si->si_pid; 727 lsi->lsi_uid = si->si_uid; 728 729 if (si->si_code == CLD_STOPPED) 730 lsi->lsi_status = BSD_TO_LINUX_SIGNAL(si->si_status); 731 else if (si->si_code == CLD_CONTINUED) 732 lsi->lsi_status = BSD_TO_LINUX_SIGNAL(SIGCONT); 733 else 734 lsi->lsi_status = si->si_status; 735 break; 736 737 case LINUX_SIGBUS: 738 case LINUX_SIGILL: 739 case LINUX_SIGFPE: 740 case LINUX_SIGSEGV: 741 lsi->lsi_addr = PTROUT(si->si_addr); 742 break; 743 744 default: 745 lsi->lsi_pid = si->si_pid; 746 lsi->lsi_uid = si->si_uid; 747 if (sig >= LINUX_SIGRTMIN) { 748 lsi->lsi_int = si->si_value.sival_int; 749 lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr); 750 } 751 break; 752 } 753 break; 754 } 755} 756 757void 758lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig) 759{ 760 761 ksi->ksi_signo = sig; 762 ksi->ksi_code = lsi->lsi_code; /* XXX. Convert. */ 763 ksi->ksi_pid = lsi->lsi_pid; 764 ksi->ksi_uid = lsi->lsi_uid; 765 ksi->ksi_status = lsi->lsi_status; 766 ksi->ksi_addr = PTRIN(lsi->lsi_addr); 767 ksi->ksi_info.si_value.sival_int = lsi->lsi_int; 768} 769 770int 771linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args) 772{ 773 l_siginfo_t linfo; 774 struct proc *p; 775 ksiginfo_t ksi; 776 int error; 777 int sig; 778 779 if (!LINUX_SIG_VALID(args->sig)) 780 return (EINVAL); 781 782 error = copyin(args->info, &linfo, sizeof(linfo)); 783 if (error != 0) 784 return (error); 785 786 if (linfo.lsi_code >= 0) 787 return (EPERM); 788 789 sig = BSD_TO_LINUX_SIGNAL(args->sig); 790 791 error = ESRCH; 792 if ((p = pfind(args->pid)) != NULL || 793 (p = zpfind(args->pid)) != NULL) { 794 error = p_cansignal(td, p, sig); 795 if (error != 0) { 796 PROC_UNLOCK(p); 797 return (error); 798 } 799 800 ksiginfo_init(&ksi); 801 lsiginfo_to_ksiginfo(&linfo, &ksi, sig); 802 error = tdsendsignal(p, NULL, sig, &ksi); 803 PROC_UNLOCK(p); 804 } 805 806 return (error); 807} 808