Home | History | Annotate | Line # | Download | only in common
linux_signal.c revision 1.3
      1 /*	$NetBSD: linux_signal.c,v 1.3 1995/03/10 22:55:04 fvdl Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Frank van der Linden
      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. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed for the NetBSD Project
     18  *      by Frank van der Linden
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  *
     33  * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
     34  */
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/namei.h>
     39 #include <sys/proc.h>
     40 #include <sys/filedesc.h>
     41 #include <sys/ioctl.h>
     42 #include <sys/mount.h>
     43 #include <sys/kernel.h>
     44 #include <sys/signal.h>
     45 #include <sys/signalvar.h>
     46 #include <sys/malloc.h>
     47 
     48 #include <sys/syscallargs.h>
     49 
     50 #include <compat/linux/linux_types.h>
     51 #include <compat/linux/linux_syscallargs.h>
     52 #include <compat/linux/linux_util.h>
     53 #include <compat/linux/linux_signal.h>
     54 
     55 /*
     56  * Most of ths stuff in this file is taken from Christos' SVR4 emul
     57  * code. The things that need to be done are largely the same, so
     58  * re-inventing the wheel doesn't make much sense.
     59  */
     60 
     61 /*
     62  * Some boring signal conversion functions. Just a switch() for all signals;
     63  * return the converted signal number, 0 if not supported.
     64  */
     65 
     66 int
     67 bsd_to_linux_sig(sig)
     68 	int sig;
     69 {
     70 	switch(sig) {
     71 	case SIGHUP:
     72 		return LINUX_SIGHUP;
     73 	case SIGINT:
     74 		return LINUX_SIGINT;
     75 	case SIGQUIT:
     76 		return LINUX_SIGQUIT;
     77 	case SIGILL:
     78 		return LINUX_SIGILL;
     79 	case SIGTRAP:
     80 		return LINUX_SIGTRAP;
     81 	case SIGABRT:
     82 		return LINUX_SIGABRT;
     83 	case SIGFPE:
     84 		return LINUX_SIGFPE;
     85 	case SIGKILL:
     86 		return LINUX_SIGKILL;
     87 	case SIGBUS:
     88 		return LINUX_SIGBUS;
     89 	case SIGSEGV:
     90 		return LINUX_SIGSEGV;
     91 	case SIGPIPE:
     92 		return LINUX_SIGPIPE;
     93 	case SIGALRM:
     94 		return LINUX_SIGALRM;
     95 	case SIGTERM:
     96 		return LINUX_SIGTERM;
     97 	case SIGURG:
     98 		return LINUX_SIGURG;
     99 	case SIGSTOP:
    100 		return LINUX_SIGSTOP;
    101 	case SIGTSTP:
    102 		return LINUX_SIGTSTP;
    103 	case SIGCONT:
    104 		return LINUX_SIGCONT;
    105 	case SIGCHLD:
    106 		return LINUX_SIGCHLD;
    107 	case SIGTTIN:
    108 		return LINUX_SIGTTIN;
    109 	case SIGTTOU:
    110 		return LINUX_SIGTTOU;
    111 	case SIGIO:
    112 		return LINUX_SIGIO;
    113 	case SIGXCPU:
    114 		return LINUX_SIGXCPU;
    115 	case SIGXFSZ:
    116 		return LINUX_SIGXFSZ;
    117 	case SIGVTALRM:
    118 		return LINUX_SIGVTALRM;
    119 	case SIGPROF:
    120 		return LINUX_SIGPROF;
    121 	case SIGWINCH:
    122 		return LINUX_SIGWINCH;
    123 	case SIGUSR1:
    124 		return LINUX_SIGUSR1;
    125 	case SIGUSR2:
    126 		return LINUX_SIGUSR2;
    127 	/* Not supported: EMT, SYS, INFO */
    128 	}
    129 	return 0;
    130 }
    131 
    132 int
    133 linux_to_bsd_sig(sig)
    134 	int sig;
    135 {
    136 	switch(sig) {
    137 	case LINUX_SIGHUP:
    138 		return SIGHUP;
    139 	case LINUX_SIGINT:
    140 		return SIGINT;
    141 	case LINUX_SIGQUIT:
    142 		return SIGQUIT;
    143 	case LINUX_SIGILL:
    144 		return SIGILL;
    145 	case LINUX_SIGTRAP:
    146 		return SIGTRAP;
    147 	case LINUX_SIGABRT:
    148 		return SIGABRT;
    149 	case LINUX_SIGBUS:
    150 		return SIGBUS;
    151 	case LINUX_SIGFPE:
    152 		return SIGFPE;
    153 	case LINUX_SIGKILL:
    154 		return SIGKILL;
    155 	case LINUX_SIGUSR1:
    156 		return SIGUSR1;
    157 	case LINUX_SIGSEGV:
    158 		return SIGSEGV;
    159 	case LINUX_SIGUSR2:
    160 		return SIGUSR2;
    161 	case LINUX_SIGPIPE:
    162 		return SIGPIPE;
    163 	case LINUX_SIGALRM:
    164 		return SIGALRM;
    165 	case LINUX_SIGTERM:
    166 		return SIGTERM;
    167 	case LINUX_SIGCHLD:
    168 		return SIGCHLD;
    169 	case LINUX_SIGCONT:
    170 		return SIGCONT;
    171 	case LINUX_SIGSTOP:
    172 		return SIGSTOP;
    173 	case LINUX_SIGTSTP:
    174 		return SIGTSTP;
    175 	case LINUX_SIGTTIN:
    176 		return SIGTTIN;
    177 	case LINUX_SIGTTOU:
    178 		return SIGTTOU;
    179 	case LINUX_SIGURG:
    180 		return SIGURG;
    181 	case LINUX_SIGXCPU:
    182 		return SIGXCPU;
    183 	case LINUX_SIGXFSZ:
    184 		return SIGXFSZ;
    185 	case LINUX_SIGVTALRM:
    186 		return SIGVTALRM;
    187 	case LINUX_SIGPROF:
    188 		return SIGPROF;
    189 	case LINUX_SIGWINCH:
    190 		return SIGWINCH;
    191 	case LINUX_SIGIO:
    192 		return SIGIO;
    193 	/* Not supported: STKFLT, PWR */
    194 	}
    195 	return 0;
    196 }
    197 
    198 /*
    199  * Ok, we know that Linux and BSD signals both are just an unsigned int.
    200  * Don't bother to use the sigismember() stuff for now.
    201  */
    202 static void
    203 linux_to_bsd_sigset(lss, bss)
    204 	const linux_sigset_t *lss;
    205 	sigset_t *bss;
    206 {
    207 	int i, newsig;
    208 
    209 	*bss = (sigset_t) 0;
    210 	for (i = 1; i <= LINUX_NSIG; i++) {
    211 		if (*lss & sigmask(i)) {
    212 			newsig = linux_to_bsd_sig(i);
    213 			if (newsig)
    214 				*bss |= sigmask(newsig);
    215 		}
    216 	}
    217 }
    218 
    219 void
    220 bsd_to_linux_sigset(bss, lss)
    221 	const sigset_t *bss;
    222 	linux_sigset_t *lss;
    223 {
    224 	int i, newsig;
    225 
    226 	*lss = (linux_sigset_t) 0;
    227 	for (i = 1; i <= NSIG; i++) {
    228 		if (*bss & sigmask(i)) {
    229 			newsig = bsd_to_linux_sig(i);
    230 			if (newsig)
    231 				*lss |= sigmask(newsig);
    232 		}
    233 	}
    234 }
    235 
    236 /*
    237  * Convert between Linux and BSD sigaction structures. Linux has
    238  * one extra field (sa_restorer) which we don't support. The Linux
    239  * SA_ONESHOT and SA_NOMASK flags (which together form the old
    240  * SysV signal behavior) are silently ignored. XXX
    241  */
    242 void
    243 linux_to_bsd_sigaction(lsa, bsa)
    244 	struct linux_sigaction *lsa;
    245 	struct sigaction *bsa;
    246 {
    247 	bsa->sa_handler = lsa->sa_handler;
    248 	linux_to_bsd_sigset(&bsa->sa_mask, &lsa->sa_mask);
    249 	bsa->sa_flags = 0;
    250 	bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_NOCLDSTOP,
    251 	    SA_NOCLDSTOP);
    252 	bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_ONSTACK,
    253 	    SA_ONSTACK);
    254 	bsa->sa_flags |= cvtto_bsd_mask(lsa->sa_flags, LINUX_SA_RESTART,
    255 	    SA_RESTART);
    256 }
    257 
    258 void
    259 bsd_to_linux_sigaction(bsa, lsa)
    260 	struct sigaction *bsa;
    261 	struct linux_sigaction *lsa;
    262 {
    263 	lsa->sa_handler = bsa->sa_handler;
    264 	bsd_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask);
    265 	lsa->sa_flags = 0;
    266 	lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_NOCLDSTOP,
    267 	    LINUX_SA_NOCLDSTOP);
    268 	lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_ONSTACK,
    269 	    LINUX_SA_ONSTACK);
    270 	lsa->sa_flags |= cvtto_linux_mask(bsa->sa_flags, SA_RESTART,
    271 	    LINUX_SA_RESTART);
    272 	lsa->sa_restorer = NULL;
    273 }
    274 
    275 
    276 /*
    277  * The Linux sigaction() system call. Do the usual conversions,
    278  * and just call sigaction(). Some flags and values are silently
    279  * ignored (see above).
    280  */
    281 int
    282 linux_sigaction(p, uap, retval)
    283 	register struct proc *p;
    284 	struct linux_sigaction_args /* {
    285 		syscallarg(int) signum;
    286 		syscallarg(struct linux_sigaction *) nsa;
    287 		syscallarg(struct linux_sigaction *) osa;
    288 	} */ *uap;
    289 	register_t *retval;
    290 {
    291 	struct sigaction *nbsda = NULL, *obsda = NULL, tmpbsda;
    292 	struct linux_sigaction *nlsa, *olsa, tmplsa;
    293 	struct sigaction_args sa;
    294 	caddr_t sg;
    295 	int error;
    296 
    297 	sg = stackgap_init();
    298 	olsa = SCARG(uap, osa);
    299 	nlsa = SCARG(uap, nsa);
    300 
    301 	if (olsa != NULL)
    302 		obsda = stackgap_alloc(&sg, sizeof (struct sigaction));
    303 
    304 	if (nlsa != NULL) {
    305 		nbsda = stackgap_alloc(&sg, sizeof (struct sigaction));
    306 		if ((error = copyin(nlsa, &tmplsa, sizeof tmplsa)))
    307 			return error;
    308 		linux_to_bsd_sigaction(&tmplsa, &tmpbsda);
    309 		if ((error = copyout(&tmpbsda, nbsda, sizeof tmpbsda)))
    310 			return error;
    311 	}
    312 
    313 	SCARG(&sa, signum) = linux_to_bsd_sig(SCARG(uap, signum));
    314 	SCARG(&sa, nsa) = nbsda;
    315 	SCARG(&sa, osa) = obsda;
    316 
    317 	if ((error = sigaction(p, &sa, retval)))
    318 		return error;
    319 
    320 	if (olsa != NULL) {
    321 		if ((error = copyin(obsda, &tmpbsda, sizeof tmpbsda)))
    322 			return error;
    323 		bsd_to_linux_sigaction(&tmpbsda, &tmplsa);
    324 		if ((error = copyout(&tmplsa, olsa, sizeof tmplsa)))
    325 			return error;
    326 	}
    327 	return 0;
    328 }
    329 
    330 /*
    331  * The Linux signal() system call. I think that the signal() in the C
    332  * library actually calls sigaction, so I doubt this one is ever used.
    333  * But hey, it can't hurt having it here. The same restrictions as for
    334  * sigaction() apply.
    335  */
    336 int
    337 linux_signal(p, uap, retval)
    338 	register struct proc *p;
    339 	struct linux_signal_args /* {
    340 		syscallarg(int) sig;
    341 		syscallarg(linux_handler_t) handler;
    342 	} */ *uap;
    343 	register_t *retval;
    344 {
    345 	caddr_t sg;
    346 	struct sigaction_args sa_args;
    347 	struct sigaction *osa, *nsa, tmpsa;
    348 	int error;
    349 
    350 	sg = stackgap_init();
    351 	nsa = stackgap_alloc(&sg, sizeof *nsa);
    352 	osa = stackgap_alloc(&sg, sizeof *osa);
    353 
    354 	tmpsa.sa_handler = SCARG(uap, handler);
    355 	tmpsa.sa_mask = (sigset_t) 0;
    356 	tmpsa.sa_flags = 0;
    357 	if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
    358 		return error;
    359 
    360 	SCARG(&sa_args, signum) = linux_to_bsd_sig(SCARG(uap, sig));
    361 	SCARG(&sa_args, osa) = osa;
    362 	SCARG(&sa_args, nsa) = nsa;
    363 	if ((error = sigaction(p, &sa_args, retval)))
    364 		return error;
    365 
    366 	if ((error = copyin(osa, &tmpsa, sizeof *osa)))
    367 		return error;
    368 	retval[0] = (register_t) tmpsa.sa_handler;
    369 
    370 	return 0;
    371 }
    372 
    373 /*
    374  * This is just a copy of the svr4 compat one. I feel so creative now.
    375  */
    376 int
    377 linux_sigprocmask(p, uap, retval)
    378 	register struct proc *p;
    379 	register struct linux_sigprocmask_args /* {
    380 		syscallarg(int) how;
    381 		syscallarg(linux_sigset_t *) set;
    382 		syscallarg(linux_sigset_t * oset;
    383 	} */ *uap;
    384 	register_t *retval;
    385 {
    386 	linux_sigset_t ss;
    387 	sigset_t bs;
    388 	int error = 0;
    389 
    390 	*retval = 0;
    391 
    392 	if (SCARG(uap, oset) != NULL) {
    393 		/* Fix the return value first if needed */
    394 		bsd_to_linux_sigset(&p->p_sigmask, &ss);
    395 		if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
    396 			return error;
    397 	}
    398 
    399 	if (SCARG(uap, set) == NULL)
    400 		/* Just examine */
    401 		return 0;
    402 
    403 	if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
    404 		return error;
    405 
    406 	linux_to_bsd_sigset(&ss, &bs);
    407 
    408 	(void) splhigh();
    409 
    410 	switch (SCARG(uap, how)) {
    411 	case LINUX_SIG_BLOCK:
    412 		p->p_sigmask |= bs & ~sigcantmask;
    413 		break;
    414 
    415 	case LINUX_SIG_UNBLOCK:
    416 		p->p_sigmask &= ~bs;
    417 		break;
    418 
    419 	case LINUX_SIG_SETMASK:
    420 		p->p_sigmask = bs & ~sigcantmask;
    421 		break;
    422 
    423 	default:
    424 		error = EINVAL;
    425 		break;
    426 	}
    427 
    428 	(void) spl0();
    429 
    430 	return error;
    431 }
    432 
    433 /*
    434  * The functions below really make no distinction between an int
    435  * and [linux_]sigset_t. This is ok for now, but it might break
    436  * sometime. Then again, sigset_t is trusted to be an int everywhere
    437  * else in the kernel too.
    438  */
    439 /* ARGSUSED */
    440 int
    441 linux_siggetmask(p, uap, retval)
    442 	struct proc *p;
    443 	void *uap;
    444 	register_t *retval;
    445 {
    446 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *) retval);
    447 	return 0;
    448 }
    449 
    450 /*
    451  * The following three functions fiddle with a process' signal mask.
    452  * Convert the signal masks because of the different signal
    453  * values for Linux. The need for this is the reason why
    454  * they are here, and have not been mapped directly.
    455  */
    456 int
    457 linux_sigsetmask(p, uap, retval)
    458 	struct proc *p;
    459 	struct linux_sigsetmask_args /* {
    460 		syscallarg(linux_sigset_t) mask;
    461 	} */ *uap;
    462 	register_t *retval;
    463 {
    464 	linux_sigset_t mask;
    465 	sigset_t bsdsig;
    466 
    467 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *) retval);
    468 
    469 	mask = SCARG(uap, mask);
    470 	bsd_to_linux_sigset(&mask, &bsdsig);
    471 
    472 	splhigh();
    473 	p->p_sigmask = bsdsig & ~sigcantmask;
    474 	spl0();
    475 
    476 	return 0;
    477 }
    478 
    479 int
    480 linux_sigpending(p, uap, retval)
    481 	struct proc *p;
    482 	struct linux_sigpending_args /* {
    483 		syscallarg(linux_sigset_t *) mask;
    484 	} */ *uap;
    485 	register_t *retval;
    486 {
    487 	sigset_t bsdsig;
    488 	linux_sigset_t linuxsig;
    489 
    490 	bsdsig = p->p_siglist & p->p_sigmask;
    491 
    492 	bsd_to_linux_sigset(&bsdsig, &linuxsig);
    493 	return copyout(&linuxsig, SCARG(uap, mask), sizeof linuxsig);
    494 }
    495 
    496 int
    497 linux_sigsuspend(p, uap, retval)
    498 	struct proc *p;
    499 	struct linux_sigsuspend_args /* {
    500 		syscallarg(caddr_t) restart;
    501 		syscallarg(int) oldmask;
    502 		syscallarg(int) mask;
    503 	} */ *uap;
    504 	register_t *retval;
    505 {
    506 	struct sigsuspend_args ssa;
    507 
    508 	linux_to_bsd_sigset(&SCARG(uap, mask), &SCARG(&ssa, mask));
    509 	return sigsuspend(p, &ssa, retval);
    510 }
    511 
    512 /*
    513  * The deprecated pause(2), which is really just an instance
    514  * of sigsuspend(2).
    515  */
    516 int
    517 linux_pause(p, uap, retval)
    518 	struct proc *p;
    519 	void *uap;
    520 	register_t *retval;
    521 {
    522 	struct sigsuspend_args bsa;
    523 
    524 	SCARG(&bsa, mask) = p->p_sigmask;
    525 	return sigsuspend(p, &bsa, retval);
    526 }
    527 
    528 /*
    529  * Once more: only a signal conversion is needed.
    530  */
    531 int
    532 linux_kill(p, uap, retval)
    533 	struct proc *p;
    534 	struct linux_kill_args /* {
    535 		syscallarg(int) pid;
    536 		syscallarg(int) signum;
    537 	} */ *uap;
    538 	register_t *retval;
    539 {
    540 	SCARG(uap, signum) = linux_to_bsd_sig(SCARG(uap, signum));
    541 	return kill(p, (struct kill_args *) uap, retval);
    542 }
    543