1/*- 2 * Copyright (c) 1998 Mark Newton 3 * Copyright (c) 1994 Christos Zoulas 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 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/filedesc.h> 35#include <sys/lock.h> 36#include <sys/mutex.h> 37#include <sys/proc.h> 38#include <sys/signal.h> 39#include <sys/signalvar.h> 40#include <sys/syscallsubr.h> 41#include <sys/sysproto.h> 42 43#include <machine/cpu.h> 44 45#include <compat/svr4/svr4.h> 46#include <compat/svr4/svr4_types.h> 47#include <compat/svr4/svr4_signal.h> 48#include <compat/svr4/svr4_proto.h> 49#include <compat/svr4/svr4_util.h> 50#include <compat/svr4/svr4_ucontext.h> 51 52#define svr4_sigmask(n) (1 << (((n) - 1) & 31)) 53#define svr4_sigword(n) (((n) - 1) >> 5) 54#define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s))) 55#define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n)) 56#define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n)) 57 58void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *); 59void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *); 60void svr4_sigfillset(svr4_sigset_t *); 61 62int bsd_to_svr4_sig[SVR4_NSIG] = { 63 0, 64 SVR4_SIGHUP, 65 SVR4_SIGINT, 66 SVR4_SIGQUIT, 67 SVR4_SIGILL, 68 SVR4_SIGTRAP, 69 SVR4_SIGABRT, 70 SVR4_SIGEMT, 71 SVR4_SIGFPE, 72 SVR4_SIGKILL, 73 SVR4_SIGBUS, 74 SVR4_SIGSEGV, 75 SVR4_SIGSYS, 76 SVR4_SIGPIPE, 77 SVR4_SIGALRM, 78 SVR4_SIGTERM, 79 SVR4_SIGURG, 80 SVR4_SIGSTOP, 81 SVR4_SIGTSTP, 82 SVR4_SIGCONT, 83 SVR4_SIGCHLD, 84 SVR4_SIGTTIN, 85 SVR4_SIGTTOU, 86 SVR4_SIGIO, 87 SVR4_SIGXCPU, 88 SVR4_SIGXFSZ, 89 SVR4_SIGVTALRM, 90 SVR4_SIGPROF, 91 SVR4_SIGWINCH, 92 0, /* SIGINFO */ 93 SVR4_SIGUSR1, 94 SVR4_SIGUSR2, 95}; 96 97int svr4_to_bsd_sig[SVR4_NSIG] = { 98 0, 99 SIGHUP, 100 SIGINT, 101 SIGQUIT, 102 SIGILL, 103 SIGTRAP, 104 SIGABRT, 105 SIGEMT, 106 SIGFPE, 107 SIGKILL, 108 SIGBUS, 109 SIGSEGV, 110 SIGSYS, 111 SIGPIPE, 112 SIGALRM, 113 SIGTERM, 114 SIGUSR1, 115 SIGUSR2, 116 SIGCHLD, 117 0, /* XXX NetBSD uses SIGPWR here, but we don't seem to have one */ 118 SIGWINCH, 119 SIGURG, 120 SIGIO, 121 SIGSTOP, 122 SIGTSTP, 123 SIGCONT, 124 SIGTTIN, 125 SIGTTOU, 126 SIGVTALRM, 127 SIGPROF, 128 SIGXCPU, 129 SIGXFSZ, 130}; 131 132void 133svr4_sigfillset(s) 134 svr4_sigset_t *s; 135{ 136 int i; 137 138 svr4_sigemptyset(s); 139 for (i = 1; i < SVR4_NSIG; i++) 140 if (svr4_to_bsd_sig[i] != 0) 141 svr4_sigaddset(s, i); 142} 143 144void 145svr4_to_bsd_sigset(sss, bss) 146 const svr4_sigset_t *sss; 147 sigset_t *bss; 148{ 149 int i, newsig; 150 151 SIGEMPTYSET(*bss); 152 for (i = 1; i < SVR4_NSIG; i++) 153 if (svr4_sigismember(sss, i)) { 154 newsig = svr4_to_bsd_sig[i]; 155 if (newsig) 156 SIGADDSET(*bss, newsig); 157 } 158} 159 160void 161bsd_to_svr4_sigset(bss, sss) 162 const sigset_t *bss; 163 svr4_sigset_t *sss; 164{ 165 int i, newsig; 166 167 svr4_sigemptyset(sss); 168 for (i = 1; i < SVR4_NSIG; i++) { 169 if (SIGISMEMBER(*bss, i)) { 170 newsig = bsd_to_svr4_sig[i]; 171 if (newsig) 172 svr4_sigaddset(sss, newsig); 173 } 174 } 175} 176 177/* 178 * XXX: Only a subset of the flags is currently implemented. 179 */ 180void 181svr4_to_bsd_sigaction(ssa, bsa) 182 const struct svr4_sigaction *ssa; 183 struct sigaction *bsa; 184{ 185 186 bsa->sa_handler = (sig_t) ssa->ssa_handler; 187 svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask); 188 bsa->sa_flags = 0; 189 if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0) 190 bsa->sa_flags |= SA_ONSTACK; 191 if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0) 192 bsa->sa_flags |= SA_RESETHAND; 193 if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0) 194 bsa->sa_flags |= SA_RESTART; 195 if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0) 196 DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n")); 197 if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0) 198 bsa->sa_flags |= SA_NOCLDSTOP; 199 if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0) 200 bsa->sa_flags |= SA_NODEFER; 201 if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0) 202 bsa->sa_flags |= SA_NOCLDWAIT; 203 if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0) 204 DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n")); 205} 206 207void 208bsd_to_svr4_sigaction(bsa, ssa) 209 const struct sigaction *bsa; 210 struct svr4_sigaction *ssa; 211{ 212 213 ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler; 214 bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask); 215 ssa->ssa_flags = 0; 216 if ((bsa->sa_flags & SA_ONSTACK) != 0) 217 ssa->ssa_flags |= SVR4_SA_ONSTACK; 218 if ((bsa->sa_flags & SA_RESETHAND) != 0) 219 ssa->ssa_flags |= SVR4_SA_RESETHAND; 220 if ((bsa->sa_flags & SA_RESTART) != 0) 221 ssa->ssa_flags |= SVR4_SA_RESTART; 222 if ((bsa->sa_flags & SA_NODEFER) != 0) 223 ssa->ssa_flags |= SVR4_SA_NODEFER; 224 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 225 ssa->ssa_flags |= SVR4_SA_NOCLDSTOP; 226} 227 228void 229svr4_to_bsd_sigaltstack(sss, bss) 230 const struct svr4_sigaltstack *sss; 231 struct sigaltstack *bss; 232{ 233 234 bss->ss_sp = sss->ss_sp; 235 bss->ss_size = sss->ss_size; 236 bss->ss_flags = 0; 237 if ((sss->ss_flags & SVR4_SS_DISABLE) != 0) 238 bss->ss_flags |= SS_DISABLE; 239 if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0) 240 bss->ss_flags |= SS_ONSTACK; 241 if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0) 242 /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n"); 243} 244 245void 246bsd_to_svr4_sigaltstack(bss, sss) 247 const struct sigaltstack *bss; 248 struct svr4_sigaltstack *sss; 249{ 250 251 sss->ss_sp = bss->ss_sp; 252 sss->ss_size = bss->ss_size; 253 sss->ss_flags = 0; 254 if ((bss->ss_flags & SS_DISABLE) != 0) 255 sss->ss_flags |= SVR4_SS_DISABLE; 256 if ((bss->ss_flags & SS_ONSTACK) != 0) 257 sss->ss_flags |= SVR4_SS_ONSTACK; 258} 259 260int 261svr4_sys_sigaction(td, uap) 262 struct thread *td; 263 struct svr4_sys_sigaction_args *uap; 264{ 265 struct svr4_sigaction isa; 266 struct sigaction nbsa, obsa; 267 struct sigaction *nbsap; 268 int error; 269 270 if (uap->signum < 0 || uap->signum >= SVR4_NSIG) 271 return (EINVAL); 272 273 DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid, 274 uap->signum, 275 SVR4_SVR42BSD_SIG(uap->signum))); 276 277 if (uap->nsa != NULL) { 278 if ((error = copyin(uap->nsa, &isa, sizeof(isa))) != 0) 279 return (error); 280 svr4_to_bsd_sigaction(&isa, &nbsa); 281 nbsap = &nbsa; 282 } else 283 nbsap = NULL; 284#if defined(DEBUG_SVR4) 285 { 286 int i; 287 for (i = 0; i < 4; i++) 288 DPRINTF(("\tssa_mask[%d] = %lx\n", i, 289 isa.ssa_mask.bits[i])); 290 DPRINTF(("\tssa_handler = %p\n", isa.ssa_handler)); 291 } 292#endif 293 error = kern_sigaction(td, SVR4_SVR42BSD_SIG(uap->signum), nbsap, &obsa, 294 0); 295 if (error == 0 && uap->osa != NULL) { 296 bsd_to_svr4_sigaction(&obsa, &isa); 297 error = copyout(&isa, uap->osa, sizeof(isa)); 298 } 299 return (error); 300} 301 302int 303svr4_sys_sigaltstack(td, uap) 304 struct thread *td; 305 struct svr4_sys_sigaltstack_args *uap; 306{ 307 struct svr4_sigaltstack sss; 308 struct sigaltstack nbss, obss, *nbssp; 309 int error; 310 311 if (uap->nss != NULL) { 312 if ((error = copyin(uap->nss, &sss, sizeof(sss))) != 0) 313 return (error); 314 svr4_to_bsd_sigaltstack(&sss, &nbss); 315 nbssp = &nbss; 316 } else 317 nbssp = NULL; 318 error = kern_sigaltstack(td, nbssp, &obss); 319 if (error == 0 && uap->oss != NULL) { 320 bsd_to_svr4_sigaltstack(&obss, &sss); 321 error = copyout(&sss, uap->oss, sizeof(sss)); 322 } 323 return (error); 324} 325 326/* 327 * Stolen from the ibcs2 one 328 */ 329int 330svr4_sys_signal(td, uap) 331 struct thread *td; 332 struct svr4_sys_signal_args *uap; 333{ 334 struct proc *p; 335 int signum; 336 int error; 337 338 p = td->td_proc; 339 DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid)); 340 341 signum = SVR4_SIGNO(uap->signum); 342 if (signum < 0 || signum >= SVR4_NSIG) { 343 if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK || 344 SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK) 345 td->td_retval[0] = (int)SVR4_SIG_ERR; 346 return (EINVAL); 347 } 348 signum = SVR4_SVR42BSD_SIG(signum); 349 350 switch (SVR4_SIGCALL(uap->signum)) { 351 case SVR4_SIGDEFER_MASK: 352 if (uap->handler == SVR4_SIG_HOLD) 353 goto sighold; 354 /* FALLTHROUGH */ 355 356 case SVR4_SIGNAL_MASK: 357 { 358 struct sigaction nbsa, obsa; 359 360 nbsa.sa_handler = (sig_t) uap->handler; 361 SIGEMPTYSET(nbsa.sa_mask); 362 nbsa.sa_flags = 0; 363 if (signum != SIGALRM) 364 nbsa.sa_flags = SA_RESTART; 365 error = kern_sigaction(td, signum, &nbsa, &obsa, 0); 366 if (error != 0) { 367 DPRINTF(("signal: sigaction failed: %d\n", 368 error)); 369 td->td_retval[0] = (int)SVR4_SIG_ERR; 370 return (error); 371 } 372 td->td_retval[0] = (int)obsa.sa_handler; 373 return (0); 374 } 375 376 case SVR4_SIGHOLD_MASK: 377sighold: 378 { 379 sigset_t set; 380 381 SIGEMPTYSET(set); 382 SIGADDSET(set, signum); 383 return (kern_sigprocmask(td, SIG_BLOCK, &set, NULL, 0)); 384 } 385 386 case SVR4_SIGRELSE_MASK: 387 { 388 sigset_t set; 389 390 SIGEMPTYSET(set); 391 SIGADDSET(set, signum); 392 return (kern_sigprocmask(td, SIG_UNBLOCK, &set, NULL, 393 0)); 394 } 395 396 case SVR4_SIGIGNORE_MASK: 397 { 398 struct sigaction sa; 399 400 sa.sa_handler = SIG_IGN; 401 SIGEMPTYSET(sa.sa_mask); 402 sa.sa_flags = 0; 403 error = kern_sigaction(td, signum, &sa, NULL, 0); 404 if (error != 0) 405 DPRINTF(("sigignore: sigaction failed\n")); 406 return (error); 407 } 408 409 case SVR4_SIGPAUSE_MASK: 410 { 411 sigset_t mask; 412 413 PROC_LOCK(p); 414 mask = td->td_sigmask; 415 PROC_UNLOCK(p); 416 SIGDELSET(mask, signum); 417 return kern_sigsuspend(td, mask); 418 } 419 420 default: 421 return (ENOSYS); 422 } 423} 424 425 426int 427svr4_sys_sigprocmask(td, uap) 428 struct thread *td; 429 struct svr4_sys_sigprocmask_args *uap; 430{ 431 svr4_sigset_t sss; 432 sigset_t oss, nss; 433 sigset_t *nssp; 434 int error; 435 436 if (uap->set != NULL) { 437 if ((error = copyin(uap->set, &sss, sizeof(sss))) != 0) 438 return error; 439 svr4_to_bsd_sigset(&sss, &nss); 440 nssp = &nss; 441 } else 442 nssp = NULL; 443 444 /* SVR/4 sigprocmask flag values are the same as the FreeBSD values. */ 445 error = kern_sigprocmask(td, uap->how, nssp, &oss, 0); 446 if (error == 0 && uap->oset != NULL) { 447 bsd_to_svr4_sigset(&oss, &sss); 448 error = copyout(&sss, uap->oset, sizeof(sss)); 449 } 450 return (error); 451} 452 453int 454svr4_sys_sigpending(td, uap) 455 struct thread *td; 456 struct svr4_sys_sigpending_args *uap; 457{ 458 struct proc *p; 459 sigset_t bss; 460 svr4_sigset_t sss; 461 462 p = td->td_proc; 463 DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", p->p_pid)); 464 switch (uap->what) { 465 case 1: /* sigpending */ 466 if (uap->mask == NULL) 467 return 0; 468 PROC_LOCK(p); 469 bss = p->p_siglist; 470 SIGSETOR(bss, td->td_siglist); 471 SIGSETAND(bss, td->td_sigmask); 472 PROC_UNLOCK(p); 473 bsd_to_svr4_sigset(&bss, &sss); 474 break; 475 476 case 2: /* sigfillset */ 477 svr4_sigfillset(&sss); 478#if defined(DEBUG_SVR4) 479 { 480 int i; 481 for (i = 0; i < 4; i++) 482 DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i])); 483 } 484#endif 485 break; 486 487 default: 488 return EINVAL; 489 } 490 491 return copyout(&sss, uap->mask, sizeof(sss)); 492} 493 494int 495svr4_sys_sigsuspend(td, uap) 496 struct thread *td; 497 struct svr4_sys_sigsuspend_args *uap; 498{ 499 svr4_sigset_t sss; 500 sigset_t bss; 501 int error; 502 503 if ((error = copyin(uap->ss, &sss, sizeof(sss))) != 0) 504 return error; 505 506 svr4_to_bsd_sigset(&sss, &bss); 507 return kern_sigsuspend(td, bss); 508} 509 510 511int 512svr4_sys_kill(td, uap) 513 struct thread *td; 514 struct svr4_sys_kill_args *uap; 515{ 516 struct kill_args ka; 517 518 if (uap->signum < 0 || uap->signum >= SVR4_NSIG) 519 return (EINVAL); 520 ka.pid = uap->pid; 521 ka.signum = SVR4_SVR42BSD_SIG(uap->signum); 522 return sys_kill(td, &ka); 523} 524 525 526int 527svr4_sys_context(td, uap) 528 struct thread *td; 529 struct svr4_sys_context_args *uap; 530{ 531 struct svr4_ucontext uc; 532 int error, onstack; 533 534 switch (uap->func) { 535 case 0: 536 DPRINTF(("getcontext(%p)\n", uap->uc)); 537 PROC_LOCK(td->td_proc); 538 onstack = sigonstack(cpu_getstack(td)); 539 PROC_UNLOCK(td->td_proc); 540 svr4_getcontext(td, &uc, &td->td_sigmask, onstack); 541 return copyout(&uc, uap->uc, sizeof(uc)); 542 543 case 1: 544 DPRINTF(("setcontext(%p)\n", uap->uc)); 545 if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0) 546 return error; 547 DPRINTF(("uc_flags = %lx\n", uc.uc_flags)); 548#if defined(DEBUG_SVR4) 549 { 550 int i; 551 for (i = 0; i < 4; i++) 552 DPRINTF(("uc_sigmask[%d] = %lx\n", i, 553 uc.uc_sigmask.bits[i])); 554 } 555#endif 556 return svr4_setcontext(td, &uc); 557 558 default: 559 DPRINTF(("context(%d, %p)\n", uap->func, 560 uap->uc)); 561 return ENOSYS; 562 } 563 return 0; 564} 565 566int 567svr4_sys_pause(td, uap) 568 struct thread *td; 569 struct svr4_sys_pause_args *uap; 570{ 571 sigset_t mask; 572 573 PROC_LOCK(td->td_proc); 574 mask = td->td_sigmask; 575 PROC_UNLOCK(td->td_proc); 576 return kern_sigsuspend(td, mask); 577} 578