1 /* $NetBSD: netbsd32_signal.c,v 1.32 2009/01/11 02:45:49 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.32 2009/01/11 02:45:49 christos Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/mount.h> 36 #include <sys/stat.h> 37 #include <sys/time.h> 38 #include <sys/signalvar.h> 39 #include <sys/proc.h> 40 #include <sys/sa.h> 41 #include <sys/savar.h> 42 #include <sys/wait.h> 43 #include <sys/dirent.h> 44 45 #include <uvm/uvm_extern.h> 46 47 #include <compat/netbsd32/netbsd32.h> 48 #include <compat/netbsd32/netbsd32_conv.h> 49 #include <compat/netbsd32/netbsd32_syscallargs.h> 50 #include <compat/netbsd32/netbsd32_sa.h> 51 52 #include <compat/sys/signal.h> 53 #include <compat/sys/signalvar.h> 54 #include <compat/sys/siginfo.h> 55 #include <compat/sys/ucontext.h> 56 #include <compat/common/compat_sigaltstack.h> 57 58 #ifdef unused 59 static void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *); 60 #endif 61 62 63 int 64 netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval) 65 { 66 /* { 67 syscallarg(int) signum; 68 syscallarg(const netbsd32_sigactionp_t) nsa; 69 syscallarg(netbsd32_sigactionp_t) osa; 70 } */ 71 struct sigaction nsa, osa; 72 struct netbsd32_sigaction *sa32p, sa32; 73 int error; 74 75 if (SCARG_P32(uap, nsa)) { 76 sa32p = SCARG_P32(uap, nsa); 77 if (copyin(sa32p, &sa32, sizeof(sa32))) 78 return EFAULT; 79 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 80 nsa.sa_mask = sa32.netbsd32_sa_mask; 81 nsa.sa_flags = sa32.netbsd32_sa_flags; 82 } 83 error = sigaction1(l, SCARG(uap, signum), 84 SCARG_P32(uap, nsa) ? &nsa : 0, 85 SCARG_P32(uap, osa) ? &osa : 0, 86 NULL, 0); 87 88 if (error) 89 return (error); 90 91 if (SCARG_P32(uap, osa)) { 92 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); 93 sa32.netbsd32_sa_mask = osa.sa_mask; 94 sa32.netbsd32_sa_flags = osa.sa_flags; 95 sa32p = SCARG_P32(uap, osa); 96 if (copyout(&sa32, sa32p, sizeof(sa32))) 97 return EFAULT; 98 } 99 100 return (0); 101 } 102 103 int 104 netbsd32___sigaltstack14(struct lwp *l, const struct netbsd32___sigaltstack14_args *uap, register_t *retval) 105 { 106 /* { 107 syscallarg(const netbsd32_sigaltstackp_t) nss; 108 syscallarg(netbsd32_sigaltstackp_t) oss; 109 } */ 110 compat_sigaltstack(uap, netbsd32_sigaltstack, SS_ONSTACK, SS_DISABLE); 111 } 112 113 /* ARGSUSED */ 114 int 115 netbsd32___sigaction14(struct lwp *l, const struct netbsd32___sigaction14_args *uap, register_t *retval) 116 { 117 /* { 118 syscallarg(int) signum; 119 syscallarg(const struct sigaction *) nsa; 120 syscallarg(struct sigaction *) osa; 121 } */ 122 struct netbsd32_sigaction sa32; 123 struct sigaction nsa, osa; 124 int error; 125 126 if (SCARG_P32(uap, nsa)) { 127 error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32)); 128 if (error) 129 return (error); 130 nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler); 131 nsa.sa_mask = sa32.netbsd32_sa_mask; 132 nsa.sa_flags = sa32.netbsd32_sa_flags; 133 } 134 error = sigaction1(l, SCARG(uap, signum), 135 SCARG_P32(uap, nsa) ? &nsa : 0, 136 SCARG_P32(uap, osa) ? &osa : 0, 137 NULL, 0); 138 if (error) 139 return (error); 140 if (SCARG_P32(uap, osa)) { 141 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); 142 sa32.netbsd32_sa_mask = osa.sa_mask; 143 sa32.netbsd32_sa_flags = osa.sa_flags; 144 error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32)); 145 if (error) 146 return (error); 147 } 148 return (0); 149 } 150 151 /* ARGSUSED */ 152 int 153 netbsd32___sigaction_sigtramp(struct lwp *l, const struct netbsd32___sigaction_sigtramp_args *uap, register_t *retval) 154 { 155 /* { 156 syscallarg(int) signum; 157 syscallarg(const netbsd32_sigactionp_t) nsa; 158 syscallarg(netbsd32_sigactionp_t) osa; 159 syscallarg(netbsd32_voidp) tramp; 160 syscallarg(int) vers; 161 } */ 162 struct netbsd32_sigaction sa32; 163 struct sigaction nsa, osa; 164 int error; 165 166 if (SCARG_P32(uap, nsa)) { 167 error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32)); 168 if (error) 169 return (error); 170 nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler); 171 nsa.sa_mask = sa32.netbsd32_sa_mask; 172 nsa.sa_flags = sa32.netbsd32_sa_flags; 173 } 174 error = sigaction1(l, SCARG(uap, signum), 175 SCARG_P32(uap, nsa) ? &nsa : 0, 176 SCARG_P32(uap, osa) ? &osa : 0, 177 SCARG_P32(uap, tramp), SCARG(uap, vers)); 178 if (error) 179 return (error); 180 if (SCARG_P32(uap, osa)) { 181 NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); 182 sa32.netbsd32_sa_mask = osa.sa_mask; 183 sa32.netbsd32_sa_flags = osa.sa_flags; 184 error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32)); 185 if (error) 186 return (error); 187 } 188 return (0); 189 } 190 191 #ifdef unused 192 static void 193 netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32) 194 { 195 memset(si, 0, sizeof (*si)); 196 si->si_signo = si32->si_signo; 197 si->si_code = si32->si_code; 198 si->si_errno = si32->si_errno; 199 200 switch (si32->si_signo) { 201 case SIGILL: 202 case SIGBUS: 203 case SIGSEGV: 204 case SIGFPE: 205 case SIGTRAP: 206 si->si_addr = NETBSD32PTR64(si32->si_addr); 207 si->si_trap = si32->si_trap; 208 break; 209 case SIGALRM: 210 case SIGVTALRM: 211 case SIGPROF: 212 si->si_pid = si32->si_pid; 213 si->si_uid = si32->si_uid; 214 /* 215 * XXX sival_ptr is currently unused. 216 */ 217 si->si_value.sival_int = si32->si_value.sival_int; 218 break; 219 case SIGCHLD: 220 si->si_pid = si32->si_pid; 221 si->si_uid = si32->si_uid; 222 si->si_utime = si32->si_utime; 223 si->si_stime = si32->si_stime; 224 break; 225 case SIGURG: 226 case SIGIO: 227 si->si_band = si32->si_band; 228 si->si_fd = si32->si_fd; 229 break; 230 } 231 } 232 #endif 233 234 void 235 netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si) 236 { 237 memset(si32, 0, sizeof (*si32)); 238 si32->si_signo = si->si_signo; 239 si32->si_code = si->si_code; 240 si32->si_errno = si->si_errno; 241 242 switch (si32->si_signo) { 243 case 0: /* SA */ 244 si32->si_value.sival_int = si->si_value.sival_int; 245 break; 246 case SIGILL: 247 case SIGBUS: 248 case SIGSEGV: 249 case SIGFPE: 250 case SIGTRAP: 251 si32->si_addr = (uint32_t)(uintptr_t)si->si_addr; 252 si32->si_trap = si->si_trap; 253 break; 254 case SIGALRM: 255 case SIGVTALRM: 256 case SIGPROF: 257 si32->si_pid = si->si_pid; 258 si32->si_uid = si->si_uid; 259 /* 260 * XXX sival_ptr is currently unused. 261 */ 262 si32->si_value.sival_int = si->si_value.sival_int; 263 break; 264 case SIGCHLD: 265 si32->si_pid = si->si_pid; 266 si32->si_uid = si->si_uid; 267 si32->si_status = si->si_status; 268 si32->si_utime = si->si_utime; 269 si32->si_stime = si->si_stime; 270 break; 271 case SIGURG: 272 case SIGIO: 273 si32->si_band = si->si_band; 274 si32->si_fd = si->si_fd; 275 break; 276 } 277 } 278 279 void 280 getucontext32(struct lwp *l, ucontext32_t *ucp) 281 { 282 struct proc *p = l->l_proc; 283 284 KASSERT(mutex_owned(p->p_lock)); 285 286 ucp->uc_flags = 0; 287 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; 288 289 if (p->p_sa != NULL) 290 ucp->uc_sigmask = p->p_sa->sa_sigmask; 291 else 292 ucp->uc_sigmask = l->l_sigmask; 293 ucp->uc_flags |= _UC_SIGMASK; 294 295 /* 296 * The (unsupplied) definition of the `current execution stack' 297 * in the System V Interface Definition appears to allow returning 298 * the main context stack. 299 */ 300 if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { 301 ucp->uc_stack.ss_sp = USRSTACK32; 302 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 303 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 304 } else { 305 /* Simply copy alternate signal execution stack. */ 306 ucp->uc_stack.ss_sp = 307 (uint32_t)(intptr_t)l->l_sigstk.ss_sp; 308 ucp->uc_stack.ss_size = l->l_sigstk.ss_size; 309 ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags; 310 } 311 ucp->uc_flags |= _UC_STACK; 312 mutex_exit(p->p_lock); 313 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); 314 mutex_enter(p->p_lock); 315 } 316 317 /* 318 * getucontext32_sa: 319 * Get a ucontext32_t for use in SA upcall generation. 320 * Tweaked version of getucontext32. We 1) do not take p_lock, 2) 321 * fudge things with uc_link (which is usually NULL for libpthread 322 * code), and 3) we report an empty signal mask. 323 */ 324 void 325 getucontext32_sa(struct lwp *l, ucontext32_t *ucp) 326 { 327 struct proc *p = l->l_proc; 328 329 ucp->uc_flags = 0; 330 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; 331 332 sigemptyset(&ucp->uc_sigmask); 333 ucp->uc_flags |= _UC_SIGMASK; 334 335 /* 336 * The (unsupplied) definition of the `current execution stack' 337 * in the System V Interface Definition appears to allow returning 338 * the main context stack. 339 */ 340 if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { 341 ucp->uc_stack.ss_sp = USRSTACK32; 342 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 343 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 344 } else { 345 /* Simply copy alternate signal execution stack. */ 346 ucp->uc_stack.ss_sp = 347 (uint32_t)(intptr_t)l->l_sigstk.ss_sp; 348 ucp->uc_stack.ss_size = l->l_sigstk.ss_size; 349 ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags; 350 } 351 ucp->uc_flags |= _UC_STACK; 352 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); 353 } 354 355 /* ARGSUSED */ 356 int 357 netbsd32_getcontext(struct lwp *l, const struct netbsd32_getcontext_args *uap, register_t *retval) 358 { 359 /* { 360 syscallarg(netbsd32_ucontextp) ucp; 361 } */ 362 struct proc *p = l->l_proc; 363 ucontext32_t uc; 364 365 mutex_enter(p->p_lock); 366 getucontext32(l, &uc); 367 mutex_exit(p->p_lock); 368 369 return copyout(&uc, SCARG_P32(uap, ucp), sizeof (ucontext32_t)); 370 } 371 372 int 373 setucontext32(struct lwp *l, const ucontext32_t *ucp) 374 { 375 struct proc *p = l->l_proc; 376 int error; 377 378 KASSERT(mutex_owned(p->p_lock)); 379 380 if ((ucp->uc_flags & _UC_SIGMASK) != 0) { 381 error = sigprocmask1(l, SIG_SETMASK, &ucp->uc_sigmask, NULL); 382 if (error != 0) 383 return error; 384 } 385 386 mutex_exit(p->p_lock); 387 error = cpu_setmcontext32(l, &ucp->uc_mcontext, ucp->uc_flags); 388 mutex_enter(p->p_lock); 389 if (error != 0) 390 return (error); 391 392 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link; 393 394 /* 395 * If there was stack information, update whether or not we are 396 * still running on an alternate signal stack. 397 */ 398 if ((ucp->uc_flags & _UC_STACK) != 0) { 399 if (ucp->uc_stack.ss_flags & SS_ONSTACK) 400 l->l_sigstk.ss_flags |= SS_ONSTACK; 401 else 402 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 403 } 404 405 return 0; 406 } 407 408 /* ARGSUSED */ 409 int 410 netbsd32_setcontext(struct lwp *l, const struct netbsd32_setcontext_args *uap, register_t *retval) 411 { 412 /* { 413 syscallarg(netbsd32_ucontextp) ucp; 414 } */ 415 ucontext32_t uc; 416 int error; 417 struct proc *p = l->l_proc; 418 419 error = copyin(SCARG_P32(uap, ucp), &uc, sizeof (uc)); 420 if (error) 421 return (error); 422 if (!(uc.uc_flags & _UC_CPU)) 423 return (EINVAL); 424 mutex_enter(p->p_lock); 425 error = setucontext32(l, &uc); 426 mutex_exit(p->p_lock); 427 if (error) 428 return (error); 429 430 return (EJUSTRETURN); 431 } 432 433 static int 434 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size) 435 { 436 const siginfo_t *info = src; 437 siginfo32_t info32; 438 439 netbsd32_si_to_si32(&info32, info); 440 441 return copyout(&info32, dst, sizeof(info32)); 442 } 443 444 static int 445 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size) 446 { 447 struct timespec *ts = dst; 448 struct netbsd32_timespec ts32; 449 int error; 450 451 error = copyin(src, &ts32, sizeof(ts32)); 452 if (error) 453 return error; 454 455 netbsd32_to_timespec(&ts32, ts); 456 return 0; 457 } 458 459 static int 460 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size) 461 { 462 const struct timespec *ts = src; 463 struct netbsd32_timespec ts32; 464 465 netbsd32_from_timespec(ts, &ts32); 466 467 return copyout(&ts32, dst, sizeof(ts32)); 468 } 469 470 int 471 netbsd32_____sigtimedwait50(struct lwp *l, const struct netbsd32_____sigtimedwait50_args *uap, register_t *retval) 472 { 473 /* { 474 syscallarg(netbsd32_sigsetp_t) set; 475 syscallarg(netbsd32_siginfop_t) info; 476 syscallarg(netbsd32_timespec50p_t) timeout; 477 } */ 478 struct sys_____sigtimedwait50_args ua; 479 480 NETBSD32TOP_UAP(set, const sigset_t); 481 NETBSD32TOP_UAP(info, siginfo_t); 482 NETBSD32TOP_UAP(timeout, struct timespec); 483 484 return __sigtimedwait1(l, &ua, retval, 485 netbsd32_sigtimedwait_put_info, 486 netbsd32_sigtimedwait_fetch_timeout, 487 netbsd32_sigtimedwait_put_timeout); 488 } 489