1 /* $NetBSD: linux32_signal.c,v 1.1 2006/02/09 19:18:57 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Emmanuel Dreyfus 17 * 4. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include <sys/param.h> 34 #include <sys/ucred.h> 35 #include <sys/signalvar.h> 36 #include <sys/lwp.h> 37 #include <sys/time.h> 38 39 #include <compat/netbsd32/netbsd32.h> 40 41 #include <compat/linux32/common/linux32_types.h> 42 #include <compat/linux32/common/linux32_signal.h> 43 #include <compat/linux32/linux32_syscallargs.h> 44 45 #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s))) 46 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ 47 & (1 << ((n) - 1) % LINUX32__NSIG_BPW)) 48 #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ 49 |= (1 << ((n) - 1) % LINUX32__NSIG_BPW)) 50 51 extern const int native_to_linux32_signo[]; 52 extern const int linux32_to_native_signo[]; 53 54 void 55 linux32_to_native_sigset(bss, lss) 56 sigset_t *bss; 57 const linux32_sigset_t *lss; 58 { 59 int i, newsig; 60 61 sigemptyset(bss); 62 for (i = 1; i < LINUX32__NSIG; i++) { 63 if (linux32_sigismember(lss, i)) { 64 newsig = linux32_to_native_signo[i]; 65 if (newsig) 66 sigaddset(bss, newsig); 67 } 68 } 69 } 70 71 void 72 native_to_linux32_sigset(lss, bss) 73 linux32_sigset_t *lss; 74 const sigset_t *bss; 75 { 76 int i, newsig; 77 78 linux32_sigemptyset(lss); 79 for (i = 1; i < NSIG; i++) { 80 if (sigismember(bss, i)) { 81 newsig = native_to_linux32_signo[i]; 82 if (newsig) 83 linux32_sigaddset(lss, newsig); 84 } 85 } 86 } 87 88 unsigned int 89 native_to_linux32_sigflags(bsf) 90 const int bsf; 91 { 92 unsigned int lsf = 0; 93 if ((bsf & SA_NOCLDSTOP) != 0) 94 lsf |= LINUX32_SA_NOCLDSTOP; 95 if ((bsf & SA_NOCLDWAIT) != 0) 96 lsf |= LINUX32_SA_NOCLDWAIT; 97 if ((bsf & SA_ONSTACK) != 0) 98 lsf |= LINUX32_SA_ONSTACK; 99 if ((bsf & SA_RESTART) != 0) 100 lsf |= LINUX32_SA_RESTART; 101 if ((bsf & SA_NODEFER) != 0) 102 lsf |= LINUX32_SA_NOMASK; 103 if ((bsf & SA_RESETHAND) != 0) 104 lsf |= LINUX32_SA_ONESHOT; 105 if ((bsf & SA_SIGINFO) != 0) 106 lsf |= LINUX32_SA_SIGINFO; 107 return lsf; 108 } 109 110 int 111 linux32_to_native_sigflags(lsf) 112 const unsigned long lsf; 113 { 114 int bsf = 0; 115 if ((lsf & LINUX32_SA_NOCLDSTOP) != 0) 116 bsf |= SA_NOCLDSTOP; 117 if ((lsf & LINUX32_SA_NOCLDWAIT) != 0) 118 bsf |= SA_NOCLDWAIT; 119 if ((lsf & LINUX32_SA_ONSTACK) != 0) 120 bsf |= SA_ONSTACK; 121 if ((lsf & LINUX32_SA_RESTART) != 0) 122 bsf |= SA_RESTART; 123 if ((lsf & LINUX32_SA_ONESHOT) != 0) 124 bsf |= SA_RESETHAND; 125 if ((lsf & LINUX32_SA_NOMASK) != 0) 126 bsf |= SA_NODEFER; 127 if ((lsf & LINUX32_SA_SIGINFO) != 0) 128 bsf |= SA_SIGINFO; 129 if ((lsf & ~LINUX32_SA_ALLBITS) != 0) { 130 #ifdef DEBUG_LINUX 131 printf("linux32_old_to_native_sigflags: " 132 "%lx extra bits ignored\n", lsf); 133 #endif 134 } 135 return bsf; 136 } 137 138 void 139 linux32_to_native_sigaction(bsa, lsa) 140 struct sigaction *bsa; 141 const struct linux32_sigaction *lsa; 142 { 143 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler); 144 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 145 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags); 146 } 147 148 void 149 native_to_linux32_sigaction(lsa, bsa) 150 struct linux32_sigaction *lsa; 151 const struct sigaction *bsa; 152 { 153 lsa->linux_sa_handler = (linux32_handler_t)(long)bsa->sa_handler; 154 native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 155 lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags); 156 lsa->linux_sa_restorer = (linux32_restorer_t)NULL; 157 } 158 159 void 160 native_to_linux32_sigaltstack(lss, bss) 161 struct linux32_sigaltstack *lss; 162 const struct sigaltstack *bss; 163 { 164 lss->ss_sp = (netbsd32_voidp)(long)bss->ss_sp; 165 lss->ss_size = bss->ss_size; 166 if (bss->ss_flags & SS_ONSTACK) 167 lss->ss_flags = LINUX32_SS_ONSTACK; 168 else if (bss->ss_flags & SS_DISABLE) 169 lss->ss_flags = LINUX32_SS_DISABLE; 170 else 171 lss->ss_flags = 0; 172 } 173 174 175 void 176 native_to_linux32_old_sigset(lss, bss) 177 linux32_old_sigset_t *lss; 178 const sigset_t *bss; 179 { 180 linux32_sigset_t lsnew; 181 182 native_to_linux32_sigset(&lsnew, bss); 183 184 /* convert new sigset to old sigset */ 185 *lss = lsnew.sig[0]; 186 } 187 188 void 189 linux32_old_to_native_sigset(bss, lss) 190 sigset_t *bss; 191 const linux32_old_sigset_t *lss; 192 { 193 linux32_sigset_t ls; 194 195 bzero(&ls, sizeof(ls)); 196 ls.sig[0] = *lss; 197 198 linux32_to_native_sigset(bss, &ls); 199 } 200 201 int 202 linux32_sys_rt_sigaction(l, v, retval) 203 struct lwp *l; 204 void *v; 205 register_t *retval; 206 { 207 struct linux32_sys_rt_sigaction_args /* { 208 syscallarg(int) signum; 209 syscallarg(const linux32_sigactionp_t) nsa; 210 syscallarg(linux32_sigactionp_t) osa; 211 syscallarg(netbsd32_size_t) sigsetsize; 212 } */ *uap = v; 213 struct linux32_sigaction nls32; 214 struct linux32_sigaction ols32; 215 struct sigaction ns; 216 struct sigaction os; 217 int error; 218 int sig; 219 int vers = 0; 220 void *tramp = NULL; 221 222 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 223 return EINVAL; 224 225 if (NETBSD32PTR64(SCARG(uap, nsa)) != NULL) { 226 if ((error = copyin(NETBSD32PTR64(SCARG(uap, nsa)), 227 &nls32, sizeof(nls32))) != 0) 228 return error; 229 linux32_to_native_sigaction(&ns, &nls32); 230 } 231 232 sig = SCARG(uap, signum); 233 if (sig < 0 || sig >= LINUX32__NSIG) 234 return EINVAL; 235 if (sig > 0 && !linux32_to_native_signo[sig]) { 236 /* unknown signal... */ 237 os.sa_handler = SIG_IGN; 238 sigemptyset(&os.sa_mask); 239 os.sa_flags = 0; 240 } else { 241 if ((error = sigaction1(l->l_proc, 242 linux32_to_native_signo[sig], 243 NETBSD32PTR64(SCARG(uap, nsa)) ? &ns : NULL, 244 NETBSD32PTR64(SCARG(uap, osa)) ? &os : NULL, 245 tramp, vers)) != 0) 246 return error; 247 } 248 249 if (NETBSD32PTR64(SCARG(uap, osa)) != NULL) { 250 native_to_linux32_sigaction(&ols32, &os); 251 252 if ((error = copyout(&ols32, NETBSD32PTR64(SCARG(uap, osa)), 253 sizeof(ols32))) != 0) 254 return error; 255 } 256 257 return 0; 258 } 259 260 int 261 linux32_sys_rt_sigprocmask(l, v, retval) 262 struct lwp *l; 263 void *v; 264 register_t *retval; 265 { 266 struct linux32_sys_rt_sigprocmask_args /* { 267 syscallarg(int) how; 268 syscallarg(const linux32_sigsetp_t) set; 269 syscallarg(linux32_sigsetp_t) oset; 270 syscallarg(netbsd32_size_t) sigsetsize; 271 } */ *uap = v; 272 struct proc *p = l->l_proc; 273 linux32_sigset_t nls32, ols32; 274 sigset_t ns, os; 275 int error; 276 int how; 277 278 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 279 return EINVAL; 280 281 switch (SCARG(uap, how)) { 282 case LINUX32_SIG_BLOCK: 283 how = SIG_BLOCK; 284 break; 285 case LINUX32_SIG_UNBLOCK: 286 how = SIG_UNBLOCK; 287 break; 288 case LINUX32_SIG_SETMASK: 289 how = SIG_SETMASK; 290 break; 291 default: 292 return EINVAL; 293 break; 294 } 295 296 if (NETBSD32PTR64(SCARG(uap, set)) != NULL) { 297 if ((error = copyin(NETBSD32PTR64(SCARG(uap, set)), 298 &nls32, sizeof(nls32))) != 0) 299 return error; 300 linux32_to_native_sigset(&ns, &nls32); 301 } 302 303 if ((error = sigprocmask1(p, how, 304 NETBSD32PTR64(SCARG(uap, set)) ? &ns : NULL, 305 NETBSD32PTR64(SCARG(uap, oset)) ? &os : NULL)) != 0) 306 return error; 307 308 if (NETBSD32PTR64(SCARG(uap, oset)) != NULL) { 309 native_to_linux32_sigset(&ols32, &os); 310 if ((error = copyout(&ols32, 311 NETBSD32PTR64(SCARG(uap, oset)), sizeof(ols32))) != 0) 312 return error; 313 } 314 315 return 0; 316 } 317 318 int 319 linux32_sys_kill(l, v, retval) 320 struct lwp *l; 321 void *v; 322 register_t *retval; 323 { 324 struct linux32_sys_kill_args /* { 325 syscallarg(int) pid; 326 syscallarg(int) signum; 327 } */ *uap = v; 328 329 struct sys_kill_args ka; 330 int sig; 331 332 SCARG(&ka, pid) = SCARG(uap, pid); 333 sig = SCARG(uap, signum); 334 if (sig < 0 || sig >= LINUX32__NSIG) 335 return (EINVAL); 336 SCARG(&ka, signum) = linux32_to_native_signo[sig]; 337 return sys_kill(l, &ka, retval); 338 } 339 340 int 341 linux32_sys_rt_sigsuspend(l, v, retval) 342 struct lwp *l; 343 void *v; 344 register_t *retval; 345 { 346 struct linux32_sys_rt_sigsuspend_args /* { 347 syscallarg(linux32_sigsetp_t) unewset; 348 syscallarg(netbsd32_size_t) sigsetsize; 349 } */ *uap = v; 350 linux32_sigset_t lss; 351 sigset_t bss; 352 int error; 353 354 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 355 return EINVAL; 356 357 if ((error = copyin(NETBSD32PTR64(SCARG(uap, unewset)), 358 &lss, sizeof(linux32_sigset_t))) != 0) 359 return error; 360 361 linux32_to_native_sigset(&bss, &lss); 362 363 return sigsuspend1(l->l_proc, &bss); 364 } 365 366 int 367 linux32_sys_signal(l, v, retval) 368 struct lwp *l; 369 void *v; 370 register_t *retval; 371 { 372 struct linux32_sys_signal_args /* { 373 syscallarg(int) signum; 374 syscallarg(linux32_handler_t) handler; 375 } */ *uap = v; 376 struct proc *p = l->l_proc; 377 struct sigaction nbsa, obsa; 378 int error, sig; 379 380 *retval = -1; 381 382 sig = SCARG(uap, signum); 383 if (sig < 0 || sig >= LINUX32__NSIG) 384 return EINVAL; 385 386 nbsa.sa_handler = NETBSD32PTR64(SCARG(uap, handler)); 387 sigemptyset(&nbsa.sa_mask); 388 nbsa.sa_flags = SA_RESETHAND | SA_NODEFER; 389 390 if ((error = sigaction1(p, linux32_to_native_signo[sig], 391 &nbsa, &obsa, NULL, 0)) != 0) 392 return error; 393 394 *retval = (int)(long)obsa.sa_handler; 395 return 0; 396 } 397