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