1 /* $NetBSD: netbsd32_signal.c,v 1.17 2006/03/15 09:09:47 cube 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.17 2006/03/15 09:09:47 cube Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/malloc.h> 37 #include <sys/mount.h> 38 #include <sys/stat.h> 39 #include <sys/time.h> 40 #include <sys/signalvar.h> 41 #include <sys/proc.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 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 56 #ifdef unused 57 static void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *); 58 #endif 59 60 61 int 62 netbsd32_sigaction(l, v, retval) 63 struct lwp *l; 64 void *v; 65 register_t *retval; 66 { 67 struct netbsd32_sigaction_args /* { 68 syscallarg(int) signum; 69 syscallarg(const netbsd32_sigactionp_t) nsa; 70 syscallarg(netbsd32_sigactionp_t) osa; 71 } */ *uap = v; 72 struct sigaction nsa, osa; 73 struct netbsd32_sigaction *sa32p, sa32; 74 int error; 75 76 if (SCARG(uap, nsa)) { 77 sa32p = 78 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, nsa)); 79 if (copyin(sa32p, &sa32, sizeof(sa32))) 80 return EFAULT; 81 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 82 nsa.sa_mask = sa32.netbsd32_sa_mask; 83 nsa.sa_flags = sa32.netbsd32_sa_flags; 84 } 85 error = sigaction1(l->l_proc, SCARG(uap, signum), 86 SCARG(uap, nsa) ? &nsa : 0, 87 SCARG(uap, osa) ? &osa : 0, 88 NULL, 0); 89 90 if (error) 91 return (error); 92 93 if (SCARG(uap, osa)) { 94 sa32.netbsd32_sa_handler = (netbsd32_sigactionp_t)(u_long)osa.sa_handler; 95 sa32.netbsd32_sa_mask = osa.sa_mask; 96 sa32.netbsd32_sa_flags = osa.sa_flags; 97 sa32p = 98 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, osa)); 99 if (copyout(&sa32, sa32p, sizeof(sa32))) 100 return EFAULT; 101 } 102 103 return (0); 104 } 105 106 int 107 netbsd32___sigaltstack14(l, v, retval) 108 struct lwp *l; 109 void *v; 110 register_t *retval; 111 { 112 struct netbsd32___sigaltstack14_args /* { 113 syscallarg(const netbsd32_sigaltstackp_t) nss; 114 syscallarg(netbsd32_sigaltstackp_t) oss; 115 } */ *uap = v; 116 struct netbsd32_sigaltstack s32; 117 struct sigaltstack nss, oss; 118 int error; 119 120 if (SCARG(uap, nss)) { 121 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nss)), &s32, 122 sizeof(s32)); 123 if (error) 124 return (error); 125 nss.ss_sp = (void *)NETBSD32PTR64(s32.ss_sp); 126 nss.ss_size = (size_t)s32.ss_size; 127 nss.ss_flags = s32.ss_flags; 128 } 129 error = sigaltstack1(l->l_proc, 130 SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0); 131 if (error) 132 return (error); 133 if (SCARG(uap, oss)) { 134 s32.ss_sp = (netbsd32_voidp)(u_long)oss.ss_sp; 135 s32.ss_size = (netbsd32_size_t)oss.ss_size; 136 s32.ss_flags = oss.ss_flags; 137 error = copyout(&s32, (caddr_t)NETBSD32PTR64(SCARG(uap, oss)), 138 sizeof(s32)); 139 if (error) 140 return (error); 141 } 142 return (0); 143 } 144 145 /* ARGSUSED */ 146 int 147 netbsd32___sigaction14(l, v, retval) 148 struct lwp *l; 149 void *v; 150 register_t *retval; 151 { 152 struct netbsd32___sigaction14_args /* { 153 syscallarg(int) signum; 154 syscallarg(const struct sigaction *) nsa; 155 syscallarg(struct sigaction *) osa; 156 } */ *uap = v; 157 struct netbsd32_sigaction sa32; 158 struct sigaction nsa, osa; 159 int error; 160 161 if (SCARG(uap, nsa)) { 162 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32, 163 sizeof(sa32)); 164 if (error) 165 return (error); 166 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 167 nsa.sa_mask = sa32.netbsd32_sa_mask; 168 nsa.sa_flags = sa32.netbsd32_sa_flags; 169 } 170 error = sigaction1(l->l_proc, SCARG(uap, signum), 171 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0, 172 NULL, 0); 173 if (error) 174 return (error); 175 if (SCARG(uap, osa)) { 176 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler; 177 sa32.netbsd32_sa_mask = osa.sa_mask; 178 sa32.netbsd32_sa_flags = osa.sa_flags; 179 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)), 180 sizeof(sa32)); 181 if (error) 182 return (error); 183 } 184 return (0); 185 } 186 187 /* ARGSUSED */ 188 int 189 netbsd32___sigaction_sigtramp(l, v, retval) 190 struct lwp *l; 191 void *v; 192 register_t *retval; 193 { 194 struct netbsd32___sigaction_sigtramp_args /* { 195 syscallarg(int) signum; 196 syscallarg(const netbsd32_sigactionp_t) nsa; 197 syscallarg(netbsd32_sigactionp_t) osa; 198 syscallarg(netbsd32_voidp) tramp; 199 syscallarg(int) vers; 200 } */ *uap = v; 201 struct proc *p = l->l_proc; 202 struct netbsd32_sigaction sa32; 203 struct sigaction nsa, osa; 204 int error; 205 206 if (SCARG(uap, nsa)) { 207 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32, 208 sizeof(sa32)); 209 if (error) 210 return (error); 211 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 212 nsa.sa_mask = sa32.netbsd32_sa_mask; 213 nsa.sa_flags = sa32.netbsd32_sa_flags; 214 } 215 error = sigaction1(p, SCARG(uap, signum), 216 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0, 217 NETBSD32PTR64(SCARG(uap, tramp)), SCARG(uap, vers)); 218 if (error) 219 return (error); 220 if (SCARG(uap, osa)) { 221 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler; 222 sa32.netbsd32_sa_mask = osa.sa_mask; 223 sa32.netbsd32_sa_flags = osa.sa_flags; 224 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)), 225 sizeof(sa32)); 226 if (error) 227 return (error); 228 } 229 return (0); 230 } 231 232 #ifdef unused 233 static void 234 netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32) 235 { 236 memset(si, 0, sizeof (*si)); 237 si->si_signo = si32->si_signo; 238 si->si_code = si32->si_code; 239 si->si_errno = si32->si_errno; 240 241 switch (si32->si_signo) { 242 case SIGILL: 243 case SIGBUS: 244 case SIGSEGV: 245 case SIGFPE: 246 case SIGTRAP: 247 si->si_addr = (void *)NETBSD32PTR64(si32->si_addr); 248 si->si_trap = si32->si_trap; 249 break; 250 case SIGALRM: 251 case SIGVTALRM: 252 case SIGPROF: 253 si->si_pid = si32->si_pid; 254 si->si_uid = si32->si_uid; 255 /* 256 * XXX sival_ptr is currently unused. 257 */ 258 si->si_sigval.sival_int = si32->si_sigval.sival_int; 259 break; 260 case SIGCHLD: 261 si->si_pid = si32->si_pid; 262 si->si_uid = si32->si_uid; 263 si->si_utime = si32->si_utime; 264 si->si_stime = si32->si_stime; 265 break; 266 case SIGURG: 267 case SIGIO: 268 si->si_band = si32->si_band; 269 si->si_fd = si32->si_fd; 270 break; 271 } 272 } 273 #endif 274 275 void 276 netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si) 277 { 278 memset(si32, 0, sizeof (*si32)); 279 si32->si_signo = si->si_signo; 280 si32->si_code = si->si_code; 281 si32->si_errno = si->si_errno; 282 283 switch (si32->si_signo) { 284 case 0: /* SA */ 285 si32->si_sigval.sival_int = si->si_sigval.sival_int; 286 break; 287 case SIGILL: 288 case SIGBUS: 289 case SIGSEGV: 290 case SIGFPE: 291 case SIGTRAP: 292 si32->si_addr = (uint32_t)(uintptr_t)si->si_addr; 293 si32->si_trap = si->si_trap; 294 break; 295 case SIGALRM: 296 case SIGVTALRM: 297 case SIGPROF: 298 si32->si_pid = si->si_pid; 299 si32->si_uid = si->si_uid; 300 /* 301 * XXX sival_ptr is currently unused. 302 */ 303 si32->si_sigval.sival_int = si->si_sigval.sival_int; 304 break; 305 case SIGCHLD: 306 si32->si_pid = si->si_pid; 307 si32->si_uid = si->si_uid; 308 si32->si_status = si->si_status; 309 si32->si_utime = si->si_utime; 310 si32->si_stime = si->si_stime; 311 break; 312 case SIGURG: 313 case SIGIO: 314 si32->si_band = si->si_band; 315 si32->si_fd = si->si_fd; 316 break; 317 } 318 } 319 320 void 321 getucontext32(struct lwp *l, ucontext32_t *ucp) 322 { 323 struct proc *p; 324 325 p = l->l_proc; 326 327 ucp->uc_flags = 0; 328 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; 329 330 (void)sigprocmask1(p, 0, NULL, &ucp->uc_sigmask); 331 ucp->uc_flags |= _UC_SIGMASK; 332 333 /* 334 * The (unsupplied) definition of the `current execution stack' 335 * in the System V Interface Definition appears to allow returning 336 * the main context stack. 337 */ 338 if ((p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK) == 0) { 339 ucp->uc_stack.ss_sp = USRSTACK32; 340 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 341 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 342 } else { 343 /* Simply copy alternate signal execution stack. */ 344 ucp->uc_stack.ss_sp = 345 (uint32_t)(intptr_t)p->p_sigctx.ps_sigstk.ss_sp; 346 ucp->uc_stack.ss_size = p->p_sigctx.ps_sigstk.ss_size; 347 ucp->uc_stack.ss_flags = p->p_sigctx.ps_sigstk.ss_flags; 348 } 349 ucp->uc_flags |= _UC_STACK; 350 351 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); 352 } 353 354 /* ARGSUSED */ 355 int 356 netbsd32_getcontext(struct lwp *l, void *v, register_t *retval) 357 { 358 struct netbsd32_getcontext_args /* { 359 syscallarg(netbsd32_ucontextp) ucp; 360 } */ *uap = v; 361 ucontext32_t uc; 362 363 getucontext32(l, &uc); 364 365 return copyout(&uc, NETBSD32PTR64(SCARG(uap, ucp)), 366 sizeof (ucontext32_t)); 367 } 368 369 int 370 setucontext32(struct lwp *l, const ucontext32_t *ucp) 371 { 372 struct proc *p; 373 int error; 374 375 p = l->l_proc; 376 if ((error = cpu_setmcontext32(l, &ucp->uc_mcontext, 377 ucp->uc_flags)) != 0) 378 return (error); 379 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link; 380 /* 381 * We might want to take care of the stack portion here but currently 382 * don't; see the comment in getucontext(). 383 */ 384 if ((ucp->uc_flags & _UC_SIGMASK) != 0) 385 sigprocmask1(p, SIG_SETMASK, &ucp->uc_sigmask, NULL); 386 387 return 0; 388 } 389 390 /* ARGSUSED */ 391 int 392 netbsd32_setcontext(struct lwp *l, void *v, register_t *retval) 393 { 394 struct netbsd32_setcontext_args /* { 395 syscallarg(netbsd32_ucontextp) ucp; 396 } */ *uap = v; 397 ucontext32_t uc; 398 int error; 399 void *p; 400 401 p = NETBSD32PTR64(SCARG(uap, ucp)); 402 if (p == NULL) 403 exit1(l, W_EXITCODE(0, 0)); 404 else if ((error = copyin(p, &uc, sizeof (uc))) != 0 || 405 (error = setucontext32(l, &uc)) != 0) 406 return (error); 407 408 return (EJUSTRETURN); 409 } 410 411 static int 412 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size) 413 { 414 const siginfo_t *info = src; 415 siginfo32_t info32; 416 417 netbsd32_si_to_si32(&info32, info); 418 419 return copyout(&info32, dst, sizeof(info32)); 420 } 421 422 static int 423 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size) 424 { 425 struct timespec *ts = dst; 426 struct netbsd32_timespec ts32; 427 int error; 428 429 error = copyin(src, &ts32, sizeof(ts32)); 430 if (error) 431 return error; 432 433 netbsd32_to_timespec(&ts32, ts); 434 return 0; 435 } 436 437 static int 438 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size) 439 { 440 const struct timespec *ts = src; 441 struct netbsd32_timespec ts32; 442 443 netbsd32_from_timespec(ts, &ts32); 444 445 return copyout(&ts32, dst, sizeof(ts32)); 446 } 447 448 int 449 netbsd32___sigtimedwait(struct lwp *l, void *v, register_t *retval) 450 { 451 struct netbsd32___sigtimedwait_args /* { 452 syscallarg(netbsd32_sigsetp_t) set; 453 syscallarg(netbsd32_siginfop_t) info; 454 syscallarg(netbsd32_timespecp_t) timeout; 455 } */ *uap = v; 456 struct sys___sigtimedwait_args ua; 457 458 NETBSD32TOP_UAP(set, const sigset_t); 459 NETBSD32TOP_UAP(info, siginfo_t); 460 NETBSD32TOP_UAP(timeout, struct timespec); 461 462 return __sigtimedwait1(l, &ua, retval, netbsd32_sigtimedwait_put_info, 463 netbsd32_sigtimedwait_fetch_timeout, 464 netbsd32_sigtimedwait_put_timeout); 465 } 466