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 withough 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 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/sysproto.h> 34 #include <sys/proc.h> 35 #include <sys/signalvar.h> 36 37 #include <machine/../linux/linux.h> 38 #include <machine/../linux/linux_proto.h> 39 #include <compat/linux/linux_signal.h> 40 #include <compat/linux/linux_util.h> 41 42 void 43 linux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss) 44 { 45 int b, l; 46 47 SIGEMPTYSET(*bss); 48 bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 49 bss->__bits[1] = lss->__bits[1]; 50 for (l = 1; l <= LINUX_SIGTBLSZ; l++) { 51 if (LINUX_SIGISMEMBER(*lss, l)) { 52 #ifdef __alpha__ 53 b = _SIG_IDX(l); 54 #else 55 b = linux_to_bsd_signal[_SIG_IDX(l)]; 56 #endif 57 if (b) 58 SIGADDSET(*bss, b); 59 } 60 } 61 } 62 63 void 64 bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) 65 { 66 int b, l; 67 68 LINUX_SIGEMPTYSET(*lss); 69 lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); 70 lss->__bits[1] = bss->__bits[1]; 71 for (b = 1; b <= LINUX_SIGTBLSZ; b++) { 72 if (SIGISMEMBER(*bss, b)) { 73 #if __alpha__ 74 l = _SIG_IDX(b); 75 #else 76 l = bsd_to_linux_signal[_SIG_IDX(b)]; 77 #endif 78 if (l) 79 LINUX_SIGADDSET(*lss, l); 80 } 81 } 82 } 83 84 static void 85 linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) 86 { 87 88 linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); 89 bsa->sa_handler = lsa->lsa_handler; 90 bsa->sa_flags = 0; 91 if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) 92 bsa->sa_flags |= SA_NOCLDSTOP; 93 if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) 94 bsa->sa_flags |= SA_NOCLDWAIT; 95 if (lsa->lsa_flags & LINUX_SA_SIGINFO) 96 bsa->sa_flags |= SA_SIGINFO; 97 if (lsa->lsa_flags & LINUX_SA_ONSTACK) 98 bsa->sa_flags |= SA_ONSTACK; 99 if (lsa->lsa_flags & LINUX_SA_RESTART) 100 bsa->sa_flags |= SA_RESTART; 101 if (lsa->lsa_flags & LINUX_SA_ONESHOT) 102 bsa->sa_flags |= SA_RESETHAND; 103 if (lsa->lsa_flags & LINUX_SA_NOMASK) 104 bsa->sa_flags |= SA_NODEFER; 105 } 106 107 static void 108 bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) 109 { 110 111 bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); 112 lsa->lsa_handler = bsa->sa_handler; 113 lsa->lsa_restorer = NULL; /* unsupported */ 114 lsa->lsa_flags = 0; 115 if (bsa->sa_flags & SA_NOCLDSTOP) 116 lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; 117 if (bsa->sa_flags & SA_NOCLDWAIT) 118 lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; 119 if (bsa->sa_flags & SA_SIGINFO) 120 lsa->lsa_flags |= LINUX_SA_SIGINFO; 121 if (bsa->sa_flags & SA_ONSTACK) 122 lsa->lsa_flags |= LINUX_SA_ONSTACK; 123 if (bsa->sa_flags & SA_RESTART) 124 lsa->lsa_flags |= LINUX_SA_RESTART; 125 if (bsa->sa_flags & SA_RESETHAND) 126 lsa->lsa_flags |= LINUX_SA_ONESHOT; 127 if (bsa->sa_flags & SA_NODEFER) 128 lsa->lsa_flags |= LINUX_SA_NOMASK; 129 } 130 131 int 132 linux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa, 133 linux_sigaction_t *linux_osa) 134 { 135 struct sigaction *nsa, *osa; 136 struct sigaction_args sa_args; 137 int error; 138 caddr_t sg = stackgap_init(); 139 140 if (linux_sig <= 0 || linux_sig > LINUX_NSIG) 141 return (EINVAL); 142 143 if (linux_osa != NULL) 144 osa = stackgap_alloc(&sg, sizeof(struct sigaction)); 145 else 146 osa = NULL; 147 148 if (linux_nsa != NULL) { 149 nsa = stackgap_alloc(&sg, sizeof(struct sigaction)); 150 linux_to_bsd_sigaction(linux_nsa, nsa); 151 } 152 else 153 nsa = NULL; 154 155 #ifndef __alpha__ 156 if (linux_sig <= LINUX_SIGTBLSZ) 157 sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; 158 else 159 #endif 160 sa_args.sig = linux_sig; 161 162 sa_args.act = nsa; 163 sa_args.oact = osa; 164 error = sigaction(p, &sa_args); 165 if (error) 166 return (error); 167 168 if (linux_osa != NULL) 169 bsd_to_linux_sigaction(osa, linux_osa); 170 171 return (0); 172 } 173 174 175 #ifndef __alpha__ 176 int 177 linux_signal(struct proc *p, struct linux_signal_args *args) 178 { 179 linux_sigaction_t nsa, osa; 180 int error; 181 182 #ifdef DEBUG 183 if (ldebug(signal)) 184 printf(ARGS(signal, "%d, %p"), 185 args->sig, (void *)args->handler); 186 #endif 187 188 nsa.lsa_handler = args->handler; 189 nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; 190 LINUX_SIGEMPTYSET(nsa.lsa_mask); 191 192 error = linux_do_sigaction(p, args->sig, &nsa, &osa); 193 p->p_retval[0] = (int)osa.lsa_handler; 194 195 return (error); 196 } 197 #endif /*!__alpha__*/ 198 199 int 200 linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) 201 { 202 linux_sigaction_t nsa, osa; 203 int error; 204 205 #ifdef DEBUG 206 if (ldebug(rt_sigaction)) 207 printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), 208 (long)args->sig, (void *)args->act, 209 (void *)args->oact, (long)args->sigsetsize); 210 #endif 211 212 if (args->sigsetsize != sizeof(linux_sigset_t)) 213 return (EINVAL); 214 215 if (args->act != NULL) { 216 error = copyin(args->act, &nsa, sizeof(linux_sigaction_t)); 217 if (error) 218 return (error); 219 } 220 221 error = linux_do_sigaction(p, args->sig, 222 args->act ? &nsa : NULL, 223 args->oact ? &osa : NULL); 224 225 if (args->oact != NULL && !error) { 226 error = copyout(&osa, args->oact, sizeof(linux_sigaction_t)); 227 } 228 229 return (error); 230 } 231 232 static int 233 linux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, 234 linux_sigset_t *old) 235 { 236 int error; 237 sigset_t mask; 238 239 error = 0; 240 p->p_retval[0] = 0; 241 242 PROC_LOCK(p); 243 if (old != NULL) 244 bsd_to_linux_sigset(&p->p_sigmask, old); 245 246 if (new != NULL) { 247 linux_to_bsd_sigset(new, &mask); 248 249 switch (how) { 250 case LINUX_SIG_BLOCK: 251 SIGSETOR(p->p_sigmask, mask); 252 SIG_CANTMASK(p->p_sigmask); 253 break; 254 case LINUX_SIG_UNBLOCK: 255 SIGSETNAND(p->p_sigmask, mask); 256 break; 257 case LINUX_SIG_SETMASK: 258 p->p_sigmask = mask; 259 SIG_CANTMASK(p->p_sigmask); 260 break; 261 default: 262 error = EINVAL; 263 break; 264 } 265 } 266 PROC_UNLOCK(p); 267 268 return (error); 269 } 270 271 #ifndef __alpha__ 272 int 273 linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) 274 { 275 linux_osigset_t mask; 276 linux_sigset_t set, oset; 277 int error; 278 279 #ifdef DEBUG 280 if (ldebug(sigprocmask)) 281 printf(ARGS(sigprocmask, "%d, *, *"), args->how); 282 #endif 283 284 if (args->mask != NULL) { 285 error = copyin(args->mask, &mask, sizeof(linux_osigset_t)); 286 if (error) 287 return (error); 288 LINUX_SIGEMPTYSET(set); 289 set.__bits[0] = mask; 290 } 291 292 error = linux_do_sigprocmask(p, args->how, 293 args->mask ? &set : NULL, 294 args->omask ? &oset : NULL); 295 296 if (args->omask != NULL && !error) { 297 mask = oset.__bits[0]; 298 error = copyout(&mask, args->omask, sizeof(linux_osigset_t)); 299 } 300 301 return (error); 302 } 303 #endif /*!__alpha__*/ 304 305 int 306 linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) 307 { 308 linux_sigset_t set, oset; 309 int error; 310 311 #ifdef DEBUG 312 if (ldebug(rt_sigprocmask)) 313 printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), 314 args->how, (void *)args->mask, 315 (void *)args->omask, (long)args->sigsetsize); 316 #endif 317 318 if (args->sigsetsize != sizeof(linux_sigset_t)) 319 return EINVAL; 320 321 if (args->mask != NULL) { 322 error = copyin(args->mask, &set, sizeof(linux_sigset_t)); 323 if (error) 324 return (error); 325 } 326 327 error = linux_do_sigprocmask(p, args->how, 328 args->mask ? &set : NULL, 329 args->omask ? &oset : NULL); 330 331 if (args->omask != NULL && !error) { 332 error = copyout(&oset, args->omask, sizeof(linux_sigset_t)); 333 } 334 335 return (error); 336 } 337 338 #ifndef __alpha__ 339 int 340 linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) 341 { 342 linux_sigset_t mask; 343 344 #ifdef DEBUG 345 if (ldebug(siggetmask)) 346 printf(ARGS(siggetmask, "")); 347 #endif 348 349 PROC_LOCK(p); 350 bsd_to_linux_sigset(&p->p_sigmask, &mask); 351 PROC_UNLOCK(p); 352 p->p_retval[0] = mask.__bits[0]; 353 return (0); 354 } 355 356 int 357 linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args) 358 { 359 linux_sigset_t lset; 360 sigset_t bset; 361 362 #ifdef DEBUG 363 if (ldebug(sigsetmask)) 364 printf(ARGS(sigsetmask, "%08lx"), (unsigned long)args->mask); 365 #endif 366 367 PROC_LOCK(p); 368 bsd_to_linux_sigset(&p->p_sigmask, &lset); 369 p->p_retval[0] = lset.__bits[0]; 370 LINUX_SIGEMPTYSET(lset); 371 lset.__bits[0] = args->mask; 372 linux_to_bsd_sigset(&lset, &bset); 373 p->p_sigmask = bset; 374 SIG_CANTMASK(p->p_sigmask); 375 PROC_UNLOCK(p); 376 return (0); 377 } 378 379 int 380 linux_sigpending(struct proc *p, struct linux_sigpending_args *args) 381 { 382 sigset_t bset; 383 linux_sigset_t lset; 384 linux_osigset_t mask; 385 386 #ifdef DEBUG 387 if (ldebug(sigpending)) 388 printf(ARGS(sigpending, "*")); 389 #endif 390 391 PROC_LOCK(p); 392 bset = p->p_siglist; 393 SIGSETAND(bset, p->p_sigmask); 394 bsd_to_linux_sigset(&bset, &lset); 395 PROC_UNLOCK(p); 396 mask = lset.__bits[0]; 397 return (copyout(&mask, args->mask, sizeof(mask))); 398 } 399 #endif /*!__alpha__*/ 400 401 int 402 linux_kill(struct proc *p, struct linux_kill_args *args) 403 { 404 struct kill_args /* { 405 int pid; 406 int signum; 407 } */ tmp; 408 409 #ifdef DEBUG 410 if (ldebug(kill)) 411 printf(ARGS(kill, "%d, %d"), args->pid, args->signum); 412 #endif 413 414 /* 415 * Allow signal 0 as a means to check for privileges 416 */ 417 if (args->signum < 0 || args->signum > LINUX_NSIG) 418 return EINVAL; 419 420 #ifndef __alpha__ 421 if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) 422 tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; 423 else 424 #endif 425 tmp.signum = args->signum; 426 427 tmp.pid = args->pid; 428 return (kill(p, &tmp)); 429 } 430