1/* $NetBSD: src/sys/compat/svr4/svr4_signal.c,v 1.64 2008-04-28 20:23:45 martin Exp $ */ 2 3/*- 4 * Copyright (c) 1994, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas and by Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: src/sys/compat/svr4/svr4_signal.c,v 1.64 2008-04-28 20:23:45 martin Exp $"); 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/namei.h> 38#include <sys/proc.h> 39#include <sys/filedesc.h> 40#include <sys/ioctl.h> 41#include <sys/mount.h> 42#include <sys/kernel.h> 43#include <sys/signal.h> 44#include <sys/signalvar.h> 45#include <sys/malloc.h> 46#include <sys/wait.h> 47 48#include <sys/syscallargs.h> 49 50#include <uvm/uvm_extern.h> 51 52#include <compat/svr4/svr4_types.h> 53#include <compat/svr4/svr4_signal.h> 54#include <compat/svr4/svr4_lwp.h> 55#include <compat/svr4/svr4_ucontext.h> 56#include <compat/svr4/svr4_syscallargs.h> 57#include <compat/svr4/svr4_util.h> 58 59#include <compat/common/compat_sigaltstack.h> 60 61#define svr4_sigmask(n) (1 << (((n) - 1) & 31)) 62#define svr4_sigword(n) (((n) - 1) >> 5) 63#define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s))) 64#define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n)) 65#define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n)) 66 67static inline void svr4_sigfillset(svr4_sigset_t *); 68void svr4_to_native_sigaction(const struct svr4_sigaction *, 69 struct sigaction *); 70void native_to_svr4_sigaction(const struct sigaction *, 71 struct svr4_sigaction *); 72 73extern const int native_to_svr4_signo[]; 74extern const int svr4_to_native_signo[]; 75 76static inline void 77svr4_sigfillset(svr4_sigset_t *s) 78{ 79 int i; 80 81 svr4_sigemptyset(s); 82 for (i = 1; i < SVR4_NSIG; i++) 83 if (svr4_to_native_signo[i] != 0) 84 svr4_sigaddset(s, i); 85} 86 87void 88svr4_to_native_sigset(const svr4_sigset_t *sss, sigset_t *bss) 89{ 90 int i, newsig; 91 92 sigemptyset(bss); 93 for (i = 1; i < SVR4_NSIG; i++) { 94 if (svr4_sigismember(sss, i)) { 95 newsig = svr4_to_native_signo[i]; 96 if (newsig) 97 sigaddset(bss, newsig); 98 } 99 } 100} 101 102 103void 104native_to_svr4_sigset(const sigset_t *bss, svr4_sigset_t *sss) 105{ 106 int i, newsig; 107 108 svr4_sigemptyset(sss); 109 for (i = 1; i < NSIG; i++) { 110 if (sigismember(bss, i)) { 111 newsig = native_to_svr4_signo[i]; 112 if (newsig) 113 svr4_sigaddset(sss, newsig); 114 } 115 } 116} 117 118/* 119 * XXX: Only a subset of the flags is currently implemented. 120 */ 121void 122svr4_to_native_sigaction(const struct svr4_sigaction *ssa, struct sigaction *bsa) 123{ 124 125 bsa->sa_handler = (sig_t) ssa->svr4_sa_handler; 126 svr4_to_native_sigset(&ssa->svr4_sa_mask, &bsa->sa_mask); 127 bsa->sa_flags = 0; 128 if ((ssa->svr4_sa_flags & SVR4_SA_ONSTACK) != 0) 129 bsa->sa_flags |= SA_ONSTACK; 130 if ((ssa->svr4_sa_flags & SVR4_SA_RESETHAND) != 0) 131 bsa->sa_flags |= SA_RESETHAND; 132 if ((ssa->svr4_sa_flags & SVR4_SA_RESTART) != 0) 133 bsa->sa_flags |= SA_RESTART; 134 if ((ssa->svr4_sa_flags & SVR4_SA_SIGINFO) != 0) 135 bsa->sa_flags |= SA_SIGINFO; 136 if ((ssa->svr4_sa_flags & SVR4_SA_NODEFER) != 0) 137 bsa->sa_flags |= SA_NODEFER; 138 if ((ssa->svr4_sa_flags & SVR4_SA_NOCLDWAIT) != 0) 139 bsa->sa_flags |= SA_NOCLDWAIT; 140 if ((ssa->svr4_sa_flags & SVR4_SA_NOCLDSTOP) != 0) 141 bsa->sa_flags |= SA_NOCLDSTOP; 142 if ((ssa->svr4_sa_flags & ~SVR4_SA_ALLBITS) != 0) { 143 DPRINTF(("svr4_to_native_sigaction: extra bits %x ignored\n", 144 ssa->svr4_sa_flags & ~SVR4_SA_ALLBITS)); 145 } 146} 147 148void 149native_to_svr4_sigaction(const struct sigaction *bsa, struct svr4_sigaction *ssa) 150{ 151 152 ssa->svr4_sa_handler = (svr4_sig_t) bsa->sa_handler; 153 native_to_svr4_sigset(&bsa->sa_mask, &ssa->svr4_sa_mask); 154 ssa->svr4_sa_flags = 0; 155 if ((bsa->sa_flags & SA_ONSTACK) != 0) 156 ssa->svr4_sa_flags |= SVR4_SA_ONSTACK; 157 if ((bsa->sa_flags & SA_RESETHAND) != 0) 158 ssa->svr4_sa_flags |= SVR4_SA_RESETHAND; 159 if ((bsa->sa_flags & SA_RESTART) != 0) 160 ssa->svr4_sa_flags |= SVR4_SA_RESTART; 161 if ((bsa->sa_flags & SA_NODEFER) != 0) 162 ssa->svr4_sa_flags |= SVR4_SA_NODEFER; 163 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 164 ssa->svr4_sa_flags |= SVR4_SA_NOCLDSTOP; 165} 166 167int 168svr4_sys_sigaction(struct lwp *l, const struct svr4_sys_sigaction_args *uap, register_t *retval) 169{ 170 /* { 171 syscallarg(int) signum; 172 syscallarg(const struct svr4_sigaction *) nsa; 173 syscallarg(struct svr4_sigaction *) osa; 174 } */ 175 struct svr4_sigaction nssa, ossa; 176 struct sigaction nbsa, obsa; 177 int error; 178 179 if (SCARG(uap, nsa)) { 180 error = copyin(SCARG(uap, nsa), &nssa, sizeof(nssa)); 181 if (error) 182 return (error); 183 svr4_to_native_sigaction(&nssa, &nbsa); 184 } 185 error = sigaction1(l, svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))], 186 SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0, 187 NULL, 0); 188 if (error) 189 return (error); 190 if (SCARG(uap, osa)) { 191 native_to_svr4_sigaction(&obsa, &ossa); 192 error = copyout(&ossa, SCARG(uap, osa), sizeof(ossa)); 193 if (error) 194 return (error); 195 } 196 return (0); 197} 198 199int 200svr4_sys_sigaltstack(struct lwp *l, const struct svr4_sys_sigaltstack_args *uap, register_t *retval) 201{ 202 /* { 203 syscallarg(const struct svr4_sigaltstack *) nss; 204 syscallarg(struct svr4_sigaltstack *) oss; 205 } */ 206 compat_sigaltstack(uap, svr4_sigaltstack, 207 SVR4_SS_ONSTACK, SVR4_SS_DISABLE); 208} 209 210/* 211 * Stolen from the ibcs2 one 212 */ 213int 214svr4_sys_signal(struct lwp *l, const struct svr4_sys_signal_args *uap, register_t *retval) 215{ 216 /* { 217 syscallarg(int) signum; 218 syscallarg(svr4_sig_t) handler; 219 } */ 220 int signum = svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))]; 221 struct proc *p = l->l_proc; 222 struct sigaction nbsa, obsa; 223 sigset_t ss; 224 int error; 225 226 if (signum <= 0 || signum >= SVR4_NSIG) 227 return (EINVAL); 228 229 switch (SVR4_SIGCALL(SCARG(uap, signum))) { 230 case SVR4_SIGDEFER_MASK: 231 if (SCARG(uap, handler) == SVR4_SIG_HOLD) 232 goto sighold; 233 /* FALLTHROUGH */ 234 235 case SVR4_SIGNAL_MASK: 236 nbsa.sa_handler = (sig_t)SCARG(uap, handler); 237 sigemptyset(&nbsa.sa_mask); 238 nbsa.sa_flags = 0; 239 error = sigaction1(l, signum, &nbsa, &obsa, NULL, 0); 240 if (error) 241 return (error); 242 *retval = (u_int)(u_long)obsa.sa_handler; 243 return (0); 244 245 case SVR4_SIGHOLD_MASK: 246 sighold: 247 sigemptyset(&ss); 248 sigaddset(&ss, signum); 249 mutex_enter(p->p_lock); 250 error = sigprocmask1(l, SIG_BLOCK, &ss, 0); 251 mutex_exit(p->p_lock); 252 return error; 253 254 case SVR4_SIGRELSE_MASK: 255 sigemptyset(&ss); 256 sigaddset(&ss, signum); 257 mutex_enter(p->p_lock); 258 error = sigprocmask1(l, SIG_UNBLOCK, &ss, 0); 259 mutex_exit(p->p_lock); 260 return error; 261 262 case SVR4_SIGIGNORE_MASK: 263 nbsa.sa_handler = SIG_IGN; 264 sigemptyset(&nbsa.sa_mask); 265 nbsa.sa_flags = 0; 266 return (sigaction1(l, signum, &nbsa, 0, NULL, 0)); 267 268 case SVR4_SIGPAUSE_MASK: 269 ss = l->l_sigmask; /* XXXAD locking */ 270 sigdelset(&ss, signum); 271 return (sigsuspend1(l, &ss)); 272 273 default: 274 return (ENOSYS); 275 } 276} 277 278int 279svr4_sys_sigprocmask(struct lwp *l, const struct svr4_sys_sigprocmask_args *uap, register_t *retval) 280{ 281 /* { 282 syscallarg(int) how; 283 syscallarg(const svr4_sigset_t *) set; 284 syscallarg(svr4_sigset_t *) oset; 285 } */ 286 struct proc *p = l->l_proc; 287 svr4_sigset_t nsss, osss; 288 sigset_t nbss, obss; 289 int how; 290 int error; 291 292 /* 293 * Initialize how to 0 to avoid a compiler warning. Note that 294 * this is safe because of the check in the default: case. 295 */ 296 how = 0; 297 298 switch (SCARG(uap, how)) { 299 case SVR4_SIG_BLOCK: 300 how = SIG_BLOCK; 301 break; 302 case SVR4_SIG_UNBLOCK: 303 how = SIG_UNBLOCK; 304 break; 305 case SVR4_SIG_SETMASK: 306 how = SIG_SETMASK; 307 break; 308 default: 309 if (SCARG(uap, set)) 310 return EINVAL; 311 break; 312 } 313 314 if (SCARG(uap, set)) { 315 error = copyin(SCARG(uap, set), &nsss, sizeof(nsss)); 316 if (error) 317 return error; 318 svr4_to_native_sigset(&nsss, &nbss); 319 } 320 mutex_enter(p->p_lock); 321 error = sigprocmask1(l, how, 322 SCARG(uap, set) ? &nbss : NULL, SCARG(uap, oset) ? &obss : NULL); 323 mutex_exit(p->p_lock); 324 if (error) 325 return error; 326 if (SCARG(uap, oset)) { 327 native_to_svr4_sigset(&obss, &osss); 328 error = copyout(&osss, SCARG(uap, oset), sizeof(osss)); 329 if (error) 330 return error; 331 } 332 return 0; 333} 334 335int 336svr4_sys_sigpending(struct lwp *l, const struct svr4_sys_sigpending_args *uap, register_t *retval) 337{ 338 /* { 339 syscallarg(int) what; 340 syscallarg(svr4_sigset_t *) set; 341 } */ 342 sigset_t bss; 343 svr4_sigset_t sss; 344 345 switch (SCARG(uap, what)) { 346 case 1: /* sigpending */ 347 sigpending1(l, &bss); 348 native_to_svr4_sigset(&bss, &sss); 349 break; 350 351 case 2: /* sigfillset */ 352 svr4_sigfillset(&sss); 353 break; 354 355 default: 356 return (EINVAL); 357 } 358 return (copyout(&sss, SCARG(uap, set), sizeof(sss))); 359} 360 361int 362svr4_sys_sigsuspend(struct lwp *l, const struct svr4_sys_sigsuspend_args *uap, register_t *retval) 363{ 364 /* { 365 syscallarg(const svr4_sigset_t *) set; 366 } */ 367 svr4_sigset_t sss; 368 sigset_t bss; 369 int error; 370 371 if (SCARG(uap, set)) { 372 error = copyin(SCARG(uap, set), &sss, sizeof(sss)); 373 if (error) 374 return (error); 375 svr4_to_native_sigset(&sss, &bss); 376 } 377 378 return (sigsuspend1(l, SCARG(uap, set) ? &bss : 0)); 379} 380 381int 382svr4_sys_pause(struct lwp *l, const void *v, register_t *retval) 383{ 384 385 return (sigsuspend1(l, 0)); 386} 387 388int 389svr4_sys_kill(struct lwp *l, const struct svr4_sys_kill_args *uap, register_t *retval) 390{ 391 /* { 392 syscallarg(int) pid; 393 syscallarg(int) signum; 394 } */ 395 struct sys_kill_args ka; 396 397 SCARG(&ka, pid) = SCARG(uap, pid); 398 SCARG(&ka, signum) = svr4_to_native_signo[SVR4_SIGNO(SCARG(uap, signum))]; 399 return sys_kill(l, &ka, retval); 400} 401 402void 403svr4_getcontext(struct lwp *l, struct svr4_ucontext *uc) 404{ 405 sigset_t mask; 406 struct proc *p = l->l_proc; 407 408 svr4_getmcontext(l, &uc->uc_mcontext, &uc->uc_flags); 409 uc->uc_link = l->l_ctxlink; 410 411 /* 412 * The (unsupplied) definition of the `current execution stack' 413 * in the System V Interface Definition appears to allow returning 414 * the main context stack. 415 */ 416 if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { 417 uc->uc_stack.ss_sp = (void *)USRSTACK; 418 uc->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 419 uc->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 420 } else { 421 /* Simply copy alternate signal execution stack. */ 422 uc->uc_stack.ss_sp = l->l_sigstk.ss_sp; 423 uc->uc_stack.ss_size = l->l_sigstk.ss_size; 424 uc->uc_stack.ss_flags = l->l_sigstk.ss_flags; 425 } 426 (void)sigprocmask1(l, 0, NULL, &mask); 427 428 native_to_svr4_sigset(&mask, &uc->uc_sigmask); 429 uc->uc_flags |= _UC_SIGMASK | _UC_STACK; 430} 431 432 433int 434svr4_setcontext(struct lwp *l, struct svr4_ucontext *uc) 435{ 436 struct proc *p = l->l_proc; 437 sigset_t mask; 438 439 if (uc->uc_flags & _UC_SIGMASK) { 440 svr4_to_native_sigset(&uc->uc_sigmask, &mask); 441 mutex_enter(p->p_lock); 442 sigprocmask1(l, SIG_SETMASK, &mask, NULL); 443 mutex_exit(p->p_lock); 444 } 445 446 /* Ignore the stack; see comment in svr4_getcontext. */ 447 448 l->l_ctxlink = uc->uc_link; 449 svr4_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 450 451 return EJUSTRETURN; 452} 453 454int 455svr4_sys_context(struct lwp *l, const struct svr4_sys_context_args *uap, register_t *retval) 456{ 457 /* { 458 syscallarg(int) func; 459 syscallarg(struct svr4_ucontext *) uc; 460 } */ 461 int error; 462 svr4_ucontext_t uc; 463 *retval = 0; 464 465 memset(&uc, 0, sizeof(uc)); 466 467 switch (SCARG(uap, func)) { 468 case SVR4_GETCONTEXT: 469 DPRINTF(("getcontext(%p)\n", SCARG(uap, uc))); 470 svr4_getcontext(l, &uc); 471 return (copyout(&uc, SCARG(uap, uc), sizeof (*SCARG(uap, uc)))); 472 473 474 case SVR4_SETCONTEXT: 475 DPRINTF(("setcontext(%p)\n", SCARG(uap, uc))); 476 error = copyin(SCARG(uap, uc), &uc, sizeof (uc)); 477 if (error) 478 return (error); 479 svr4_setcontext(l, &uc); 480 return EJUSTRETURN; 481 482 default: 483 DPRINTF(("context(%d, %p)\n", SCARG(uap, func), 484 SCARG(uap, uc))); 485 return ENOSYS; 486 } 487} 488