1 /* $NetBSD: netbsd32_signal.c,v 1.27 2007/12/08 18:36:19 dsl 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.27 2007/12/08 18:36:19 dsl 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(struct lwp *l, void *v, register_t *retval) 64 { 65 struct netbsd32_sigaction_args /* { 66 syscallarg(int) signum; 67 syscallarg(const netbsd32_sigactionp_t) nsa; 68 syscallarg(netbsd32_sigactionp_t) osa; 69 } */ *uap = v; 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, void *v, register_t *retval) 104 { 105 struct netbsd32___sigaltstack14_args /* { 106 syscallarg(const netbsd32_sigaltstackp_t) nss; 107 syscallarg(netbsd32_sigaltstackp_t) oss; 108 } */ *uap = v; 109 compat_sigaltstack(uap, netbsd32_sigaltstack, SS_ONSTACK, SS_DISABLE); 110 } 111 112 /* ARGSUSED */ 113 int 114 netbsd32___sigaction14(struct lwp *l, void *v, register_t *retval) 115 { 116 struct netbsd32___sigaction14_args /* { 117 syscallarg(int) signum; 118 syscallarg(const struct sigaction *) nsa; 119 syscallarg(struct sigaction *) osa; 120 } */ *uap = v; 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, void *v, register_t *retval) 153 { 154 struct netbsd32___sigaction_sigtramp_args /* { 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 } */ *uap = v; 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_smutex)); 284 285 ucp->uc_flags = 0; 286 ucp->uc_link = (uint32_t)(intptr_t)l->l_ctxlink; 287 288 ucp->uc_sigmask = l->l_sigmask; 289 ucp->uc_flags |= _UC_SIGMASK; 290 291 /* 292 * The (unsupplied) definition of the `current execution stack' 293 * in the System V Interface Definition appears to allow returning 294 * the main context stack. 295 */ 296 if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { 297 ucp->uc_stack.ss_sp = USRSTACK32; 298 ucp->uc_stack.ss_size = ctob(p->p_vmspace->vm_ssize); 299 ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ 300 } else { 301 /* Simply copy alternate signal execution stack. */ 302 ucp->uc_stack.ss_sp = 303 (uint32_t)(intptr_t)l->l_sigstk.ss_sp; 304 ucp->uc_stack.ss_size = l->l_sigstk.ss_size; 305 ucp->uc_stack.ss_flags = l->l_sigstk.ss_flags; 306 } 307 ucp->uc_flags |= _UC_STACK; 308 mutex_exit(&p->p_smutex); 309 cpu_getmcontext32(l, &ucp->uc_mcontext, &ucp->uc_flags); 310 mutex_enter(&p->p_smutex); 311 } 312 313 /* ARGSUSED */ 314 int 315 netbsd32_getcontext(struct lwp *l, void *v, register_t *retval) 316 { 317 struct netbsd32_getcontext_args /* { 318 syscallarg(netbsd32_ucontextp) ucp; 319 } */ *uap = v; 320 struct proc *p = l->l_proc; 321 ucontext32_t uc; 322 323 mutex_enter(&p->p_smutex); 324 getucontext32(l, &uc); 325 mutex_exit(&p->p_smutex); 326 327 return copyout(&uc, SCARG_P32(uap, ucp), sizeof (ucontext32_t)); 328 } 329 330 int 331 setucontext32(struct lwp *l, const ucontext32_t *ucp) 332 { 333 struct proc *p = l->l_proc; 334 int error; 335 336 KASSERT(mutex_owned(&p->p_smutex)); 337 338 if ((ucp->uc_flags & _UC_SIGMASK) != 0) { 339 error = sigprocmask1(l, SIG_SETMASK, &ucp->uc_sigmask, NULL); 340 if (error != 0) 341 return error; 342 } 343 344 mutex_exit(&p->p_smutex); 345 error = cpu_setmcontext32(l, &ucp->uc_mcontext, ucp->uc_flags); 346 mutex_enter(&p->p_smutex); 347 if (error != 0) 348 return (error); 349 350 l->l_ctxlink = (void *)(intptr_t)ucp->uc_link; 351 352 /* 353 * If there was stack information, update whether or not we are 354 * still running on an alternate signal stack. 355 */ 356 if ((ucp->uc_flags & _UC_STACK) != 0) { 357 if (ucp->uc_stack.ss_flags & SS_ONSTACK) 358 l->l_sigstk.ss_flags |= SS_ONSTACK; 359 else 360 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 361 } 362 363 return 0; 364 } 365 366 /* ARGSUSED */ 367 int 368 netbsd32_setcontext(struct lwp *l, void *v, register_t *retval) 369 { 370 struct netbsd32_setcontext_args /* { 371 syscallarg(netbsd32_ucontextp) ucp; 372 } */ *uap = v; 373 ucontext32_t uc; 374 int error; 375 struct proc *p = l->l_proc; 376 377 error = copyin(SCARG_P32(uap, ucp), &uc, sizeof (uc)); 378 if (error) 379 return (error); 380 if (!(uc.uc_flags & _UC_CPU)) 381 return (EINVAL); 382 mutex_enter(&p->p_smutex); 383 error = setucontext32(l, &uc); 384 mutex_exit(&p->p_smutex); 385 if (error) 386 return (error); 387 388 return (EJUSTRETURN); 389 } 390 391 static int 392 netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size) 393 { 394 const siginfo_t *info = src; 395 siginfo32_t info32; 396 397 netbsd32_si_to_si32(&info32, info); 398 399 return copyout(&info32, dst, sizeof(info32)); 400 } 401 402 static int 403 netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size) 404 { 405 struct timespec *ts = dst; 406 struct netbsd32_timespec ts32; 407 int error; 408 409 error = copyin(src, &ts32, sizeof(ts32)); 410 if (error) 411 return error; 412 413 netbsd32_to_timespec(&ts32, ts); 414 return 0; 415 } 416 417 static int 418 netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size) 419 { 420 const struct timespec *ts = src; 421 struct netbsd32_timespec ts32; 422 423 netbsd32_from_timespec(ts, &ts32); 424 425 return copyout(&ts32, dst, sizeof(ts32)); 426 } 427 428 int 429 netbsd32___sigtimedwait(struct lwp *l, void *v, register_t *retval) 430 { 431 struct netbsd32___sigtimedwait_args /* { 432 syscallarg(netbsd32_sigsetp_t) set; 433 syscallarg(netbsd32_siginfop_t) info; 434 syscallarg(netbsd32_timespecp_t) timeout; 435 } */ *uap = v; 436 struct sys___sigtimedwait_args ua; 437 438 NETBSD32TOP_UAP(set, const sigset_t); 439 NETBSD32TOP_UAP(info, siginfo_t); 440 NETBSD32TOP_UAP(timeout, struct timespec); 441 442 return __sigtimedwait1(l, &ua, retval, netbsd32_sigtimedwait_put_info, 443 netbsd32_sigtimedwait_fetch_timeout, 444 netbsd32_sigtimedwait_put_timeout); 445 } 446