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