1 /*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/proc.h> 37 #include <sys/signalvar.h> 38 #include <sys/syscallsubr.h> 39 #include <sys/sysproto.h> 40 41 #include <machine/../linux/linux.h> 42 #include <machine/../linux/linux_proto.h> 43 #include <compat/linux/linux_signal.h> 44 #include <compat/linux/linux_util.h> 45 46 void 47 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 48 { 49 int b, l; 50 51 SIGEMPTYSET(*bss); 52 bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 53 bss->__bits[1] = lss->__bits[1]; 54 for (l = 1; l <= LINUX_SIGTBLSZ; l++) { 55 if (LINUX_SIGISMEMBER(*lss, l)) { 56 #ifdef __alpha__ 57 b = _SIG_IDX(l); 58 #else 59 b = linux_to_bsd_signal[_SIG_IDX(l)]; 60 #endif 61 if (b) 62 SIGADDSET(*bss, b); 63 } 64 } 65 } 66 67 void 68 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 69 { 70 int b, l; 71 72 LINUX_SIGEMPTYSET(*lss); 73 lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 74 lss->__bits[1] = bss->__bits[1]; 75 for (b = 1; b <= LINUX_SIGTBLSZ; b++) { 76 if (SIGISMEMBER(*bss, b)) { 77 #if __alpha__ 78 l = _SIG_IDX(b); 79 #else 80 l = bsd_to_linux_signal[_SIG_IDX(b)]; 81 #endif 82 if (l) 83 LINUX_SIGADDSET(*lss, l); 84 } 85 } 86 } 87 88 static void 89 linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa) 90 { 91 92 linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); 93 bsa->sa_handler = lsa->lsa_handler; 94 bsa->sa_flags = 0; 95 if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) 96 bsa->sa_flags |= SA_NOCLDSTOP; 97 if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) 98 bsa->sa_flags |= SA_NOCLDWAIT; 99 if (lsa->lsa_flags & LINUX_SA_SIGINFO) 100 bsa->sa_flags |= SA_SIGINFO; 101 if (lsa->lsa_flags & LINUX_SA_ONSTACK) 102 bsa->sa_flags |= SA_ONSTACK; 103 if (lsa->lsa_flags & LINUX_SA_RESTART) 104 bsa->sa_flags |= SA_RESTART; 105 if (lsa->lsa_flags & LINUX_SA_ONESHOT) 106 bsa->sa_flags |= SA_RESETHAND; 107 if (lsa->lsa_flags & LINUX_SA_NOMASK) 108 bsa->sa_flags |= SA_NODEFER; 109 } 110 111 static void 112 bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa) 113 { 114 115 bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); 116 lsa->lsa_handler = bsa->sa_handler; 117 lsa->lsa_restorer = NULL; /* unsupported */ 118 lsa->lsa_flags = 0; 119 if (bsa->sa_flags & SA_NOCLDSTOP) 120 lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; 121 if (bsa->sa_flags & SA_NOCLDWAIT) 122 lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; 123 if (bsa->sa_flags & SA_SIGINFO) 124 lsa->lsa_flags |= LINUX_SA_SIGINFO; 125 if (bsa->sa_flags & SA_ONSTACK) 126 lsa->lsa_flags |= LINUX_SA_ONSTACK; 127 if (bsa->sa_flags & SA_RESTART) 128 lsa->lsa_flags |= LINUX_SA_RESTART; 129 if (bsa->sa_flags & SA_RESETHAND) 130 lsa->lsa_flags |= LINUX_SA_ONESHOT; 131 if (bsa->sa_flags & SA_NODEFER) 132 lsa->lsa_flags |= LINUX_SA_NOMASK; 133 } 134 135 int 136 linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa, 137 l_sigaction_t *linux_osa) 138 { 139 struct sigaction act, oact, *nsa, *osa; 140 int error, sig; 141 142 if (linux_sig <= 0 || linux_sig > LINUX_NSIG) 143 return (EINVAL); 144 145 osa = (linux_osa != NULL) ? &oact : NULL; 146 if (linux_nsa != NULL) { 147 nsa = &act; 148 linux_to_bsd_sigaction(linux_nsa, nsa); 149 } else 150 nsa = NULL; 151 152 #ifndef __alpha__ 153 if (linux_sig <= LINUX_SIGTBLSZ) 154 sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; 155 else 156 #endif 157 sig = linux_sig; 158 159 error = kern_sigaction(td, sig, nsa, osa, 0); 160 if (error) 161 return (error); 162 163 if (linux_osa != NULL) 164 bsd_to_linux_sigaction(osa, linux_osa); 165 166 return (0); 167 } 168 169 170 #ifndef __alpha__ 171 int 172 linux_signal(struct thread *td, struct linux_signal_args *args) 173 { 174 l_sigaction_t nsa, osa; 175 int error; 176 177 #ifdef DEBUG 178 if (ldebug(signal)) 179 printf(ARGS(signal, "%d, %p"), 180 args->sig, (void *)args->handler); 181 #endif 182 183 nsa.lsa_handler = args->handler; 184 nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 185 LINUX_SIGEMPTYSET(nsa.lsa_mask); 186 187 error = linux_do_sigaction(td, args->sig, &nsa, &osa); 188 td->td_retval[0] = (int)osa.lsa_handler; 189 190 return (error); 191 } 192 #endif /*!__alpha__*/ 193 194 int 195 linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args) 196 { 197 l_sigaction_t nsa, osa; 198 int error; 199 200 #ifdef DEBUG 201 if (ldebug(rt_sigaction)) 202 printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), 203 (long)args->sig, (void *)args->act, 204 (void *)args->oact, (long)args->sigsetsize); 205 #endif 206 207 if (args->sigsetsize != sizeof(l_sigset_t)) 208 return (EINVAL); 209 210 if (args->act != NULL) { 211 error = copyin(args->act, &nsa, sizeof(l_sigaction_t)); 212 if (error) 213 return (error); 214 } 215 216 error = linux_do_sigaction(td, args->sig, 217 args->act ? &nsa : NULL, 218 args->oact ? &osa : NULL); 219 220 if (args->oact != NULL && !error) { 221 error = copyout(&osa, args->oact, sizeof(l_sigaction_t)); 222 } 223 224 return (error); 225 } 226 227 static int 228 linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new, 229 l_sigset_t *old) 230 { 231 sigset_t omask, nmask; 232 sigset_t *nmaskp; 233 int error; 234 235 td->td_retval[0] = 0; 236 237 switch (how) { 238 case LINUX_SIG_BLOCK: 239 how = SIG_BLOCK; 240 break; 241 case LINUX_SIG_UNBLOCK: 242 how = SIG_UNBLOCK; 243 break; 244 case LINUX_SIG_SETMASK: 245 how = SIG_SETMASK; 246 break; 247 default: 248 return (EINVAL); 249 } 250 if (new != NULL) { 251 linux_to_bsd_sigset(new, &nmask); 252 nmaskp = &nmask; 253 } else 254 nmaskp = NULL; 255 error = kern_sigprocmask(td, how, nmaskp, &omask, 0); 256 if (error == 0 && old != NULL) 257 bsd_to_linux_sigset(&omask, old); 258 259 return (error); 260 } 261 262 #ifndef __alpha__ 263 int 264 linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args) 265 { 266 l_osigset_t mask; 267 l_sigset_t set, oset; 268 int error; 269 270 #ifdef DEBUG 271 if (ldebug(sigprocmask)) 272 printf(ARGS(sigprocmask, "%d, *, *"), args->how); 273 #endif 274 275 if (args->mask != NULL) { 276 error = copyin(args->mask, &mask, sizeof(l_osigset_t)); 277 if (error) 278 return (error); 279 LINUX_SIGEMPTYSET(set); 280 set.__bits[0] = mask; 281 } 282 283 error = linux_do_sigprocmask(td, args->how, 284 args->mask ? &set : NULL, 285 args->omask ? &oset : NULL); 286 287 if (args->omask != NULL && !error) { 288 mask = oset.__bits[0]; 289 error = copyout(&mask, args->omask, sizeof(l_osigset_t)); 290 } 291 292 return (error); 293 } 294 #endif /*!__alpha__*/ 295 296 int 297 linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args) 298 { 299 l_sigset_t set, oset; 300 int error; 301 302 #ifdef DEBUG 303 if (ldebug(rt_sigprocmask)) 304 printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 305 args->how, (void *)args->mask, 306 (void *)args->omask, (long)args->sigsetsize); 307 #endif 308 309 if (args->sigsetsize != sizeof(l_sigset_t)) 310 return EINVAL; 311 312 if (args->mask != NULL) { 313 error = copyin(args->mask, &set, sizeof(l_sigset_t)); 314 if (error) 315 return (error); 316 } 317 318 error = linux_do_sigprocmask(td, args->how, 319 args->mask ? &set : NULL, 320 args->omask ? &oset : NULL); 321 322 if (args->omask != NULL && !error) { 323 error = copyout(&oset, args->omask, sizeof(l_sigset_t)); 324 } 325 326 return (error); 327 } 328 329 #ifndef __alpha__ 330 int 331 linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args) 332 { 333 struct proc *p = td->td_proc; 334 l_sigset_t mask; 335 336 #ifdef DEBUG 337 if (ldebug(sgetmask)) 338 printf(ARGS(sgetmask, "")); 339 #endif 340 341 PROC_LOCK(p); 342 bsd_to_linux_sigset(&td->td_sigmask, &mask); 343 PROC_UNLOCK(p); 344 td->td_retval[0] = mask.__bits[0]; 345 return (0); 346 } 347 348 int 349 linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) 350 { 351 struct proc *p = td->td_proc; 352 l_sigset_t lset; 353 sigset_t bset; 354 355 #ifdef DEBUG 356 if (ldebug(ssetmask)) 357 printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); 358 #endif 359 360 PROC_LOCK(p); 361 bsd_to_linux_sigset(&td->td_sigmask, &lset); 362 td->td_retval[0] = lset.__bits[0]; 363 LINUX_SIGEMPTYSET(lset); 364 lset.__bits[0] = args->mask; 365 linux_to_bsd_sigset(&lset, &bset); 366 td->td_sigmask = bset; 367 SIG_CANTMASK(td->td_sigmask); 368 signotify(td); 369 PROC_UNLOCK(p); 370 return (0); 371 } 372 373 /* 374 * MPSAFE 375 */ 376 int 377 linux_sigpending(struct thread *td, struct linux_sigpending_args *args) 378 { 379 struct proc *p = td->td_proc; 380 sigset_t bset; 381 l_sigset_t lset; 382 l_osigset_t mask; 383 384 #ifdef DEBUG 385 if (ldebug(sigpending)) 386 printf(ARGS(sigpending, "*")); 387 #endif 388 389 PROC_LOCK(p); 390 bset = p->p_siglist; 391 SIGSETOR(bset, td->td_siglist); 392 SIGSETAND(bset, td->td_sigmask); 393 PROC_UNLOCK(p); 394 bsd_to_linux_sigset(&bset, &lset); 395 mask = lset.__bits[0]; 396 return (copyout(&mask, args->mask, sizeof(mask))); 397 } 398 #endif /*!__alpha__*/ 399 400 int 401 linux_kill(struct thread *td, struct linux_kill_args *args) 402 { 403 struct kill_args /* { 404 int pid; 405 int signum; 406 } */ tmp; 407 408 #ifdef DEBUG 409 if (ldebug(kill)) 410 printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 411 #endif 412 413 /* 414 * Allow signal 0 as a means to check for privileges 415 */ 416 if (args->signum < 0 || args->signum > LINUX_NSIG) 417 return EINVAL; 418 419 #ifndef __alpha__ 420 if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 421 tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 422 else 423 #endif 424 tmp.signum = args->signum; 425 426 tmp.pid = args->pid; 427 return (kill(td, &tmp)); 428 } 429