1 /* $NetBSD: netbsd32_signal.c,v 1.10 2005/07/23 22:03:45 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.10 2005/07/23 22:03:45 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 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 50 int 51 netbsd32_sigaction(l, v, retval) 52 struct lwp *l; 53 void *v; 54 register_t *retval; 55 { 56 struct netbsd32_sigaction_args /* { 57 syscallarg(int) signum; 58 syscallarg(const netbsd32_sigactionp_t) nsa; 59 syscallarg(netbsd32_sigactionp_t) osa; 60 } */ *uap = v; 61 struct sigaction nsa, osa; 62 struct netbsd32_sigaction *sa32p, sa32; 63 int error; 64 65 if (SCARG(uap, nsa)) { 66 sa32p = 67 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, nsa)); 68 if (copyin(sa32p, &sa32, sizeof(sa32))) 69 return EFAULT; 70 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 71 nsa.sa_mask = sa32.netbsd32_sa_mask; 72 nsa.sa_flags = sa32.netbsd32_sa_flags; 73 } 74 error = sigaction1(l->l_proc, SCARG(uap, signum), 75 SCARG(uap, nsa) ? &nsa : 0, 76 SCARG(uap, osa) ? &osa : 0, 77 NULL, 0); 78 79 if (error) 80 return (error); 81 82 if (SCARG(uap, osa)) { 83 sa32.netbsd32_sa_handler = (netbsd32_sigactionp_t)(u_long)osa.sa_handler; 84 sa32.netbsd32_sa_mask = osa.sa_mask; 85 sa32.netbsd32_sa_flags = osa.sa_flags; 86 sa32p = 87 (struct netbsd32_sigaction *)NETBSD32PTR64(SCARG(uap, osa)); 88 if (copyout(&sa32, sa32p, sizeof(sa32))) 89 return EFAULT; 90 } 91 92 return (0); 93 } 94 95 int 96 netbsd32___sigaltstack14(l, v, retval) 97 struct lwp *l; 98 void *v; 99 register_t *retval; 100 { 101 struct netbsd32___sigaltstack14_args /* { 102 syscallarg(const netbsd32_sigaltstackp_t) nss; 103 syscallarg(netbsd32_sigaltstackp_t) oss; 104 } */ *uap = v; 105 struct netbsd32_sigaltstack s32; 106 struct sigaltstack nss, oss; 107 int error; 108 109 if (SCARG(uap, nss)) { 110 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nss)), &s32, 111 sizeof(s32)); 112 if (error) 113 return (error); 114 nss.ss_sp = (void *)NETBSD32PTR64(s32.ss_sp); 115 nss.ss_size = (size_t)s32.ss_size; 116 nss.ss_flags = s32.ss_flags; 117 } 118 error = sigaltstack1(l->l_proc, 119 SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0); 120 if (error) 121 return (error); 122 if (SCARG(uap, oss)) { 123 s32.ss_sp = (netbsd32_voidp)(u_long)oss.ss_sp; 124 s32.ss_size = (netbsd32_size_t)oss.ss_size; 125 s32.ss_flags = oss.ss_flags; 126 error = copyout(&s32, (caddr_t)NETBSD32PTR64(SCARG(uap, oss)), 127 sizeof(s32)); 128 if (error) 129 return (error); 130 } 131 return (0); 132 } 133 134 /* ARGSUSED */ 135 int 136 netbsd32___sigaction14(l, v, retval) 137 struct lwp *l; 138 void *v; 139 register_t *retval; 140 { 141 struct netbsd32___sigaction14_args /* { 142 syscallarg(int) signum; 143 syscallarg(const struct sigaction *) nsa; 144 syscallarg(struct sigaction *) osa; 145 } */ *uap = v; 146 struct netbsd32_sigaction sa32; 147 struct sigaction nsa, osa; 148 int error; 149 150 if (SCARG(uap, nsa)) { 151 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32, 152 sizeof(sa32)); 153 if (error) 154 return (error); 155 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 156 nsa.sa_mask = sa32.netbsd32_sa_mask; 157 nsa.sa_flags = sa32.netbsd32_sa_flags; 158 } 159 error = sigaction1(l->l_proc, SCARG(uap, signum), 160 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0, 161 NULL, 0); 162 if (error) 163 return (error); 164 if (SCARG(uap, osa)) { 165 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler; 166 sa32.netbsd32_sa_mask = osa.sa_mask; 167 sa32.netbsd32_sa_flags = osa.sa_flags; 168 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)), 169 sizeof(sa32)); 170 if (error) 171 return (error); 172 } 173 return (0); 174 } 175 176 /* ARGSUSED */ 177 int 178 netbsd32___sigaction_sigtramp(l, v, retval) 179 struct lwp *l; 180 void *v; 181 register_t *retval; 182 { 183 struct netbsd32___sigaction_sigtramp_args /* { 184 syscallarg(int) signum; 185 syscallarg(const netbsd32_sigactionp_t) nsa; 186 syscallarg(netbsd32_sigactionp_t) osa; 187 syscallarg(netbsd32_voidp) tramp; 188 syscallarg(int) vers; 189 } */ *uap = v; 190 struct proc *p = l->l_proc; 191 struct netbsd32_sigaction sa32; 192 struct sigaction nsa, osa; 193 int error; 194 195 if (SCARG(uap, nsa)) { 196 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, nsa)), &sa32, 197 sizeof(sa32)); 198 if (error) 199 return (error); 200 nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); 201 nsa.sa_mask = sa32.netbsd32_sa_mask; 202 nsa.sa_flags = sa32.netbsd32_sa_flags; 203 } 204 error = sigaction1(p, SCARG(uap, signum), 205 SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0, 206 NETBSD32PTR64(SCARG(uap, tramp)), SCARG(uap, vers)); 207 if (error) 208 return (error); 209 if (SCARG(uap, osa)) { 210 sa32.netbsd32_sa_handler = (netbsd32_voidp)(u_long)osa.sa_handler; 211 sa32.netbsd32_sa_mask = osa.sa_mask; 212 sa32.netbsd32_sa_flags = osa.sa_flags; 213 error = copyout(&sa32, (caddr_t)NETBSD32PTR64(SCARG(uap, osa)), 214 sizeof(sa32)); 215 if (error) 216 return (error); 217 } 218 return (0); 219 } 220 221 void 222 netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32) 223 { 224 memset(si, 0, sizeof (*si)); 225 si->si_signo = si32->si_signo; 226 si->si_code = si32->si_code; 227 si->si_errno = si32->si_errno; 228 229 switch (si32->si_signo) { 230 case SIGILL: 231 case SIGBUS: 232 case SIGSEGV: 233 case SIGFPE: 234 case SIGTRAP: 235 si->si_addr = (void *)NETBSD32PTR64(si32->si_addr); 236 si->si_trap = si32->si_trap; 237 break; 238 case SIGALRM: 239 case SIGVTALRM: 240 case SIGPROF: 241 si->si_pid = si32->si_pid; 242 si->si_uid = si32->si_uid; 243 /* 244 * XXX sival_ptr is currently unused. 245 */ 246 si->si_sigval.sival_int = si32->si_sigval.sival_int; 247 break; 248 case SIGCHLD: 249 si->si_pid = si32->si_pid; 250 si->si_uid = si32->si_uid; 251 si->si_utime = si32->si_utime; 252 si->si_stime = si32->si_stime; 253 break; 254 case SIGURG: 255 case SIGIO: 256 si->si_band = si32->si_band; 257 si->si_fd = si32->si_fd; 258 break; 259 } 260 } 261 262 void 263 netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si) 264 { 265 memset(si32, 0, sizeof (*si32)); 266 si32->si_signo = si->si_signo; 267 si32->si_code = si->si_code; 268 si32->si_errno = si->si_errno; 269 270 switch (si32->si_signo) { 271 case SIGILL: 272 case SIGBUS: 273 case SIGSEGV: 274 case SIGFPE: 275 case SIGTRAP: 276 si32->si_addr = (uint32_t)(uintptr_t)si->si_addr; 277 si32->si_trap = si->si_trap; 278 break; 279 case SIGALRM: 280 case SIGVTALRM: 281 case SIGPROF: 282 si32->si_pid = si->si_pid; 283 si32->si_uid = si->si_uid; 284 /* 285 * XXX sival_ptr is currently unused. 286 */ 287 si32->si_sigval.sival_int = si->si_sigval.sival_int; 288 break; 289 case SIGCHLD: 290 si32->si_pid = si->si_pid; 291 si32->si_uid = si->si_uid; 292 si32->si_status = si->si_status; 293 si32->si_utime = si->si_utime; 294 si32->si_stime = si->si_stime; 295 break; 296 case SIGURG: 297 case SIGIO: 298 si32->si_band = si->si_band; 299 si32->si_fd = si->si_fd; 300 break; 301 } 302 } 303 304 void 305 getucontext32(struct lwp *l, ucontext32_t *ucp) 306 { 307 struct proc *p; 308 309 p = l->l_proc; 310 311 ucp->uc_flags = 0; 312 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; 313 314 (void)sigprocmask1(p, 0, NULL, &ucp->uc_sigmask); 315 ucp->uc_flags |= _UC_SIGMASK; 316 317 /* 318 * The (unsupplied) definition of the `current execution stack' 319 * in the System V Interface Definition appears to allow returning 320 * the main context stack. 321 */ 322 if ((p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK) == 0) { 323 ucp->uc_stack.ss_sp = USRSTACK32; 324 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 325 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 326 } else { 327 /* Simply copy alternate signal execution stack. */ 328 ucp->uc_stack.ss_sp = 329 (uint32_t)(intptr_t)p->p_sigctx.ps_sigstk.ss_sp; 330 ucp->uc_stack.ss_size = p->p_sigctx.ps_sigstk.ss_size; 331 ucp->uc_stack.ss_flags = p->p_sigctx.ps_sigstk.ss_flags; 332 } 333 ucp->uc_flags |= _UC_STACK; 334 335 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); 336 } 337 338 /* ARGSUSED */ 339 int 340 netbsd32_getcontext(struct lwp *l, void *v, register_t *retval) 341 { 342 struct netbsd32_getcontext_args /* { 343 syscallarg(netbsd32_ucontextp) ucp; 344 } */ *uap = v; 345 ucontext32_t uc; 346 347 getucontext32(l, &uc); 348 349 return copyout(&uc, NETBSD32PTR64(SCARG(uap, ucp)), 350 sizeof (ucontext32_t)); 351 } 352 353 int 354 setucontext32(struct lwp *l, const ucontext32_t *ucp) 355 { 356 struct proc *p; 357 int error; 358 359 p = l->l_proc; 360 if ((error = cpu_setmcontext32(l, &ucp->uc_mcontext, 361 ucp->uc_flags)) != 0) 362 return (error); 363 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link; 364 /* 365 * We might want to take care of the stack portion here but currently 366 * don't; see the comment in getucontext(). 367 */ 368 if ((ucp->uc_flags & _UC_SIGMASK) != 0) 369 sigprocmask1(p, SIG_SETMASK, &ucp->uc_sigmask, NULL); 370 371 return 0; 372 } 373 374 /* ARGSUSED */ 375 int 376 netbsd32_setcontext(struct lwp *l, void *v, register_t *retval) 377 { 378 struct netbsd32_setcontext_args /* { 379 syscallarg(netbsd32_ucontextp) ucp; 380 } */ *uap = v; 381 ucontext32_t uc; 382 int error; 383 void *p; 384 385 p = NETBSD32PTR64(SCARG(uap, ucp)); 386 if (p == NULL) 387 exit1(l, W_EXITCODE(0, 0)); 388 else if ((error = copyin(p, &uc, sizeof (uc))) != 0 || 389 (error = setucontext32(l, &uc)) != 0) 390 return (error); 391 392 return (EJUSTRETURN); 393 } 394 395 static int 396 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size) 397 { 398 const siginfo_t *info = src; 399 siginfo32_t info32; 400 401 netbsd32_si_to_si32(&info32, info); 402 403 return copyout(&info32, dst, sizeof(info32)); 404 } 405 406 static int 407 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size) 408 { 409 struct timespec *ts = dst; 410 struct netbsd32_timespec ts32; 411 int error; 412 413 error = copyin(src, &ts32, sizeof(ts32)); 414 if (error) 415 return error; 416 417 netbsd32_to_timespec(&ts32, ts); 418 return 0; 419 } 420 421 static int 422 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size) 423 { 424 const struct timespec *ts = src; 425 struct netbsd32_timespec ts32; 426 427 netbsd32_from_timespec(ts, &ts32); 428 429 return copyout(&ts32, dst, sizeof(ts32)); 430 } 431 432 int 433 netbsd32___sigtimedwait(struct lwp *l, void *v, register_t *retval) 434 { 435 struct netbsd32___sigtimedwait_args /* { 436 syscallarg(netbsd32_sigsetp_t) set; 437 syscallarg(netbsd32_siginfop_t) info; 438 syscallarg(netbsd32_timespecp_t) timeout; 439 } */ *uap = v; 440 struct sys___sigtimedwait_args ua; 441 442 NETBSD32TOP_UAP(set, const sigset_t); 443 NETBSD32TOP_UAP(info, siginfo_t); 444 NETBSD32TOP_UAP(timeout, struct timespec); 445 446 return __sigtimedwait1(l, &ua, retval, netbsd32_sigtimedwait_put_info, 447 netbsd32_sigtimedwait_fetch_timeout, 448 netbsd32_sigtimedwait_put_timeout); 449 } 450