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