1 /* $NetBSD: linux_signal.c,v 1.19 1998/10/07 22:50:42 erh 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/param.h> 57 #include <sys/systm.h> 58 #include <sys/namei.h> 59 #include <sys/proc.h> 60 #include <sys/filedesc.h> 61 #include <sys/ioctl.h> 62 #include <sys/mount.h> 63 #include <sys/kernel.h> 64 #include <sys/signal.h> 65 #include <sys/signalvar.h> 66 #include <sys/malloc.h> 67 68 #include <sys/syscallargs.h> 69 70 #include <compat/linux/common/linux_types.h> 71 #include <compat/linux/common/linux_signal.h> 72 #include <compat/linux/common/linux_siginfo.h> 73 #include <compat/linux/common/linux_util.h> 74 75 #include <compat/linux/linux_syscallargs.h> 76 77 /* Locally used defines (in bsd<->linux conversion functions): */ 78 /* XXX XAX rename to linux_old. Add stuff for new type linux_sigset_t 79 handle _NSIG_WORDS > 1 */ 80 #define linux_sigmask(n) (1 << ((n) - 1)) 81 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s))) 82 #define linux_sigismember(s, n) (*(s) & linux_sigmask(n)) 83 #define linux_sigaddset(s, n) (*(s) |= linux_sigmask(n)) 84 85 /* Note: linux_to_native_sig[] is in <arch>/linux_sigarray.c */ 86 int native_to_linux_sig[NSIG] = { 87 0, 88 LINUX_SIGHUP, 89 LINUX_SIGINT, 90 LINUX_SIGQUIT, 91 LINUX_SIGILL, 92 LINUX_SIGTRAP, 93 LINUX_SIGABRT, 94 0, /* SIGEMT */ 95 LINUX_SIGFPE, 96 LINUX_SIGKILL, 97 LINUX_SIGBUS, 98 LINUX_SIGSEGV, 99 0, /* SIGSEGV */ 100 LINUX_SIGPIPE, 101 LINUX_SIGALRM, 102 LINUX_SIGTERM, 103 LINUX_SIGURG, 104 LINUX_SIGSTOP, 105 LINUX_SIGTSTP, 106 LINUX_SIGCONT, 107 LINUX_SIGCHLD, 108 LINUX_SIGTTIN, 109 LINUX_SIGTTOU, 110 LINUX_SIGIO, 111 LINUX_SIGXCPU, 112 LINUX_SIGXFSZ, 113 LINUX_SIGVTALRM, 114 LINUX_SIGPROF, 115 LINUX_SIGWINCH, 116 0, /* SIGINFO */ 117 LINUX_SIGUSR1, 118 LINUX_SIGUSR2, 119 LINUX_SIGPWR, 120 }; 121 122 /* 123 * Ok, we know that Linux and BSD signals both are just an unsigned int. 124 * Don't bother to use the sigismember() stuff for now. 125 */ 126 void 127 linux_old_to_native_sigset(lss, bss) 128 const linux_old_sigset_t *lss; 129 sigset_t *bss; 130 { 131 int i, newsig; 132 133 sigemptyset(bss); 134 for (i = 1; i < LINUX_NSIG; i++) { 135 if (linux_sigismember(lss, i)) { 136 newsig = linux_to_native_sig[i]; 137 if (newsig) 138 sigaddset(bss, newsig); 139 } 140 } 141 } 142 143 void 144 native_to_linux_old_sigset(bss, lss) 145 const sigset_t *bss; 146 linux_old_sigset_t *lss; 147 { 148 int i, newsig; 149 150 linux_sigemptyset(lss); 151 for (i = 1; i < NSIG; i++) { 152 if (sigismember(bss, i)) { 153 newsig = native_to_linux_sig[i]; 154 if (newsig) 155 linux_sigaddset(lss, newsig); 156 } 157 } 158 } 159 160 /* 161 * Convert between Linux and BSD sigaction structures. Linux sometimes 162 * has one extra field (sa_restorer) which we don't support. 163 */ 164 void 165 linux_old_to_native_sigaction(lsa, bsa) 166 struct linux_old_sigaction *lsa; 167 struct sigaction *bsa; 168 { 169 170 bsa->sa_handler = lsa->sa_handler; 171 linux_old_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask); 172 bsa->sa_flags = 0; 173 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0) 174 bsa->sa_flags |= SA_NOCLDSTOP; 175 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0) 176 bsa->sa_flags |= SA_ONSTACK; 177 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0) 178 bsa->sa_flags |= SA_RESTART; 179 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0) 180 bsa->sa_flags |= SA_RESETHAND; 181 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0) 182 bsa->sa_flags |= SA_NODEFER; 183 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0) 184 bsa->sa_flags |= SA_SIGINFO; 185 #ifdef DEBUG 186 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0) 187 /*XXX*/ printf("linux_old_to_native_sigaction: extra bits ignored\n"); 188 if (lsa->sa_restorer != 0) 189 /*XXX*/ printf("linux_old_to_native_sigaction: sa_restorer ignored\n"); 190 #endif 191 } 192 193 void 194 native_to_linux_old_sigaction(bsa, lsa) 195 struct sigaction *bsa; 196 struct linux_old_sigaction *lsa; 197 { 198 199 /* Clear sa_flags and sa_restorer (if it exists) */ 200 bzero(lsa, sizeof(struct linux_old_sigaction)); 201 202 /* ...and fill in the mask and flags */ 203 native_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask); 204 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 205 lsa->sa_flags |= LINUX_SA_NOCLDSTOP; 206 if ((bsa->sa_flags & SA_ONSTACK) != 0) 207 lsa->sa_flags |= LINUX_SA_ONSTACK; 208 if ((bsa->sa_flags & SA_RESTART) != 0) 209 lsa->sa_flags |= LINUX_SA_RESTART; 210 if ((bsa->sa_flags & SA_NODEFER) != 0) 211 lsa->sa_flags |= LINUX_SA_NOMASK; 212 if ((bsa->sa_flags & SA_RESETHAND) != 0) 213 lsa->sa_flags |= LINUX_SA_ONESHOT; 214 if ((bsa->sa_flags & SA_SIGINFO) != 0) 215 lsa->sa_flags |= LINUX_SA_SIGINFO; 216 lsa->sa_handler = bsa->sa_handler; 217 } 218 219 /* ...and the new sigaction conversion funcs. */ 220 void 221 linux_to_native_sigaction(lsa, bsa) 222 struct linux_sigaction *lsa; 223 struct sigaction *bsa; 224 { 225 226 bsa->sa_handler = lsa->sa_handler; 227 linux_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask); 228 bsa->sa_flags = 0; 229 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0) 230 bsa->sa_flags |= SA_NOCLDSTOP; 231 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0) 232 bsa->sa_flags |= SA_ONSTACK; 233 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0) 234 bsa->sa_flags |= SA_RESTART; 235 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0) 236 bsa->sa_flags |= SA_RESETHAND; 237 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0) 238 bsa->sa_flags |= SA_NODEFER; 239 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0) 240 bsa->sa_flags |= SA_SIGINFO; 241 #ifdef DEBUG 242 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0) 243 /*XXX*/ printf("linux_to_native_sigaction: extra bits ignored\n"); 244 if (lsa->sa_restorer != 0) 245 /*XXX*/ printf("linux_to_native_sigaction: sa_restorer ignored\n"); 246 #endif 247 } 248 249 void 250 native_to_linux_sigaction(bsa, lsa) 251 struct sigaction *bsa; 252 struct linux_sigaction *lsa; 253 { 254 255 /* Clear sa_flags and sa_restorer (if it exists) */ 256 bzero(lsa, sizeof(struct linux_sigaction)); 257 258 /* ...and fill in the mask and flags */ 259 native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask); 260 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 261 lsa->sa_flags |= LINUX_SA_NOCLDSTOP; 262 if ((bsa->sa_flags & SA_ONSTACK) != 0) 263 lsa->sa_flags |= LINUX_SA_ONSTACK; 264 if ((bsa->sa_flags & SA_RESTART) != 0) 265 lsa->sa_flags |= LINUX_SA_RESTART; 266 if ((bsa->sa_flags & SA_NODEFER) != 0) 267 lsa->sa_flags |= LINUX_SA_NOMASK; 268 if ((bsa->sa_flags & SA_RESETHAND) != 0) 269 lsa->sa_flags |= LINUX_SA_ONESHOT; 270 if ((bsa->sa_flags & SA_SIGINFO) != 0) 271 lsa->sa_flags |= LINUX_SA_SIGINFO; 272 lsa->sa_handler = bsa->sa_handler; 273 } 274 275 /* ----------------------------------------------------------------------- */ 276 277 /* 278 * The Linux sigaction() system call. Do the usual conversions, 279 * and just call sigaction(). Some flags and values are silently 280 * ignored (see above). 281 */ 282 int 283 linux_sys_rt_sigaction(p, v, retval) 284 register struct proc *p; 285 void *v; 286 register_t *retval; 287 { 288 struct linux_sys_rt_sigaction_args /* { 289 syscallarg(int) signum; 290 syscallarg(const struct linux_sigaction *) nsa; 291 syscallarg(struct linux_sigaction *) osa; 292 syscallarg(size_t) sigsetsize; 293 } */ *uap = v; 294 struct linux_sigaction nlsa, olsa; 295 struct sigaction nbsa, obsa; 296 int error; 297 298 /* XXX XAX linux_sigset_t or struct linux_sigaction here? */ 299 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 300 return (EINVAL); 301 302 if (SCARG(uap, nsa)) { 303 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 304 if (error) 305 return (error); 306 linux_to_native_sigaction(&nlsa, &nbsa); 307 } 308 error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)], 309 SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0); 310 if (error) 311 return (error); 312 if (SCARG(uap, osa)) { 313 native_to_linux_sigaction(&obsa, &olsa); 314 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 315 if (error) 316 return (error); 317 } 318 return (0); 319 } 320 321 int 322 linux_sigprocmask1(p, how, set, oset) 323 register struct proc *p; 324 int how; 325 const linux_old_sigset_t *set; 326 linux_old_sigset_t *oset; 327 { 328 linux_old_sigset_t nlss, olss; 329 sigset_t nbss, obss; 330 int error; 331 332 switch (how) { 333 case LINUX_SIG_BLOCK: 334 how = SIG_BLOCK; 335 break; 336 case LINUX_SIG_UNBLOCK: 337 how = SIG_UNBLOCK; 338 break; 339 case LINUX_SIG_SETMASK: 340 how = SIG_SETMASK; 341 break; 342 default: 343 return (EINVAL); 344 } 345 346 if (set) { 347 error = copyin(set, &nlss, sizeof(nlss)); 348 if (error) 349 return (error); 350 linux_old_to_native_sigset(&nlss, &nbss); 351 } 352 error = sigprocmask1(p, how, 353 set ? &nbss : 0, oset ? &obss : 0); 354 if (error) 355 return (error); 356 if (oset) { 357 native_to_linux_old_sigset(&obss, &olss); 358 error = copyout(&olss, oset, sizeof(olss)); 359 if (error) 360 return (error); 361 } 362 return (error); 363 } 364 365 int 366 linux_sys_rt_sigprocmask(p, v, retval) 367 register struct proc *p; 368 void *v; 369 register_t *retval; 370 { 371 struct linux_sys_rt_sigprocmask_args /* { 372 syscallarg(int) how; 373 syscallarg(const linux_sigset_t *) set; 374 syscallarg(linux_sigset_t *) oset; 375 syscallarg(size_t) sigsetsize; 376 } */ *uap = v; 377 378 /* Use non-rt function: sigsetsize is ignored. */ 379 /* Assume sizeof(linux_sigset_t) == sizeof(linux_old_sigset_t) */ 380 if (SCARG(uap, sigsetsize) != sizeof(linux_old_sigset_t)) { 381 #ifdef LINUX_DEBUG 382 printf("linux_sys_rt_sigprocmask: sigsetsize != sizeof(old_sigset_t)"); 383 #endif 384 return(ENOSYS); 385 } 386 387 return(linux_sigprocmask1(p, SCARG(uap, how), 388 (const linux_old_sigset_t *)SCARG(uap, set), 389 (linux_old_sigset_t *)SCARG(uap, oset))); 390 } 391 392 int 393 linux_sys_rt_sigpending(p, v, retval) 394 register struct proc *p; 395 void *v; 396 register_t *retval; 397 { 398 struct linux_sys_rt_sigpending_args /* { 399 syscallarg(linux_sigset_t *) set; 400 syscallarg(size_t) sigsetsize; 401 } */ *uap = v; 402 sigset_t bss; 403 linux_sigset_t lss; 404 405 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 406 return (EINVAL); 407 408 sigpending1(p, &bss); 409 native_to_linux_sigset(&bss, &lss); 410 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 411 } 412 int 413 linux_sys_sigpending(p, v, retval) 414 register struct proc *p; 415 void *v; 416 register_t *retval; 417 { 418 struct linux_sys_sigpending_args /* { 419 syscallarg(linux_old_sigset_t *) mask; 420 } */ *uap = v; 421 sigset_t bss; 422 linux_old_sigset_t lss; 423 424 sigpending1(p, &bss); 425 native_to_linux_old_sigset(&bss, &lss); 426 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 427 } 428 429 int 430 linux_sys_sigsuspend(p, v, retval) 431 register struct proc *p; 432 void *v; 433 register_t *retval; 434 { 435 struct linux_sys_sigsuspend_args /* { 436 syscallarg(caddr_t) restart; 437 syscallarg(int) oldmask; 438 syscallarg(int) mask; 439 } */ *uap = v; 440 linux_old_sigset_t lss; 441 sigset_t bss; 442 443 lss = SCARG(uap, mask); 444 linux_old_to_native_sigset(&lss, &bss); 445 return (sigsuspend1(p, &bss)); 446 } 447 int 448 linux_sys_rt_sigsuspend(p, v, retval) 449 register struct proc *p; 450 void *v; 451 register_t *retval; 452 { 453 struct linux_sys_rt_sigsuspend_args /* { 454 syscallarg(linux_sigset_t *) unewset; 455 syscallarg(size_t) sigsetsize; 456 } */ *uap = v; 457 linux_sigset_t lss; 458 sigset_t bss; 459 int error; 460 461 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 462 return (EINVAL); 463 464 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 465 if (error) 466 return (error); 467 468 linux_to_native_sigset(&lss, &bss); 469 470 return (sigsuspend1(p, &bss)); 471 } 472 473 /* 474 * Once more: only a signal conversion is needed. 475 * Note: also used as sys_rt_queueinfo. The info field is ignored. 476 */ 477 int 478 linux_sys_rt_queueinfo(p, v, retval) 479 register struct proc *p; 480 void *v; 481 register_t *retval; 482 { 483 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 484 #if 0 485 struct linux_sys_rt_queueinfo_args /* { 486 syscallarg(int) pid; 487 syscallarg(int) signum; 488 syscallarg(siginfo_t *) uinfo; 489 } */ *uap = v; 490 #endif 491 492 /* XXX To really implement this we need to */ 493 /* XXX keep a list of queued signals somewhere. */ 494 return (linux_sys_kill(p, v, retval)); 495 } 496 497 int 498 linux_sys_kill(p, v, retval) 499 register struct proc *p; 500 void *v; 501 register_t *retval; 502 { 503 struct linux_sys_kill_args /* { 504 syscallarg(int) pid; 505 syscallarg(int) signum; 506 } */ *uap = v; 507 struct sys_kill_args ka; 508 509 SCARG(&ka, pid) = SCARG(uap, pid); 510 SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)]; 511 return sys_kill(p, &ka, retval); 512 } 513