Home | History | Annotate | Line # | Download | only in common
linux_signal.c revision 1.7
      1 /*	$NetBSD: linux_signal.c,v 1.7 1995/08/14 01:12:15 mycroft 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_signal.h>
     52 #include <compat/linux/linux_syscallargs.h>
     53 #include <compat/linux/linux_util.h>
     54 
     55 #define	sigemptyset(s)		bzero((s), sizeof(*(s)))
     56 #define	sigismember(s, n)	(*(s) & sigmask(n))
     57 #define	sigaddset(s, n)		(*(s) |= sigmask(n))
     58 
     59 #define	linux_sigmask(n)	(1 << ((n) - 1))
     60 #define	linux_sigemptyset(s)	bzero((s), sizeof(*(s)))
     61 #define	linux_sigismember(s, n)	(*(s) & linux_sigmask(n))
     62 #define	linux_sigaddset(s, n)	(*(s) |= linux_sigmask(n))
     63 
     64 int bsd_to_linux_sig[] = {
     65 	0,
     66 	LINUX_SIGHUP,
     67 	LINUX_SIGINT,
     68 	LINUX_SIGQUIT,
     69 	LINUX_SIGILL,
     70 	LINUX_SIGTRAP,
     71 	LINUX_SIGABRT,
     72 	0,
     73 	LINUX_SIGFPE,
     74 	LINUX_SIGKILL,
     75 	LINUX_SIGBUS,
     76 	LINUX_SIGSEGV,
     77 	0,
     78 	LINUX_SIGPIPE,
     79 	LINUX_SIGALRM,
     80 	LINUX_SIGTERM,
     81 	LINUX_SIGURG,
     82 	LINUX_SIGSTOP,
     83 	LINUX_SIGTSTP,
     84 	LINUX_SIGCONT,
     85 	LINUX_SIGCHLD,
     86 	LINUX_SIGTTIN,
     87 	LINUX_SIGTTOU,
     88 	LINUX_SIGIO,
     89 	LINUX_SIGXCPU,
     90 	LINUX_SIGXFSZ,
     91 	LINUX_SIGVTALRM,
     92 	LINUX_SIGPROF,
     93 	LINUX_SIGWINCH,
     94 	0,
     95 	LINUX_SIGUSR1,
     96 	LINUX_SIGUSR2,
     97 };
     98 
     99 int linux_to_bsd_sig[] = {
    100 	0,
    101 	SIGHUP,
    102 	SIGINT,
    103 	SIGQUIT,
    104 	SIGILL,
    105 	SIGTRAP,
    106 	SIGABRT,
    107 	SIGBUS,
    108 	SIGFPE,
    109 	SIGKILL,
    110 	SIGUSR1,
    111 	SIGSEGV,
    112 	SIGUSR2,
    113 	SIGPIPE,
    114 	SIGALRM,
    115 	SIGTERM,
    116 	0,
    117 	SIGCHLD,
    118 	SIGCONT,
    119 	SIGSTOP,
    120 	SIGTSTP,
    121 	SIGTTIN,
    122 	SIGTTOU,
    123 	SIGURG,
    124 	SIGXCPU,
    125 	SIGXFSZ,
    126 	SIGVTALRM,
    127 	SIGPROF,
    128 	SIGWINCH,
    129 	SIGIO,
    130 	0,
    131 	0,
    132 };
    133 
    134 /*
    135  * Ok, we know that Linux and BSD signals both are just an unsigned int.
    136  * Don't bother to use the sigismember() stuff for now.
    137  */
    138 void
    139 linux_to_bsd_sigset(lss, bss)
    140 	const linux_sigset_t *lss;
    141 	sigset_t *bss;
    142 {
    143 	int i, newsig;
    144 
    145 	sigemptyset(bss);
    146 	for (i = 1; i < LINUX_NSIG; i++) {
    147 		if (linux_sigismember(lss, i)) {
    148 			newsig = linux_to_bsd_sig[i];
    149 			if (newsig)
    150 				sigaddset(bss, newsig);
    151 		}
    152 	}
    153 }
    154 
    155 void
    156 bsd_to_linux_sigset(bss, lss)
    157 	const sigset_t *bss;
    158 	linux_sigset_t *lss;
    159 {
    160 	int i, newsig;
    161 
    162 	linux_sigemptyset(lss);
    163 	for (i = 1; i < NSIG; i++) {
    164 		if (sigismember(bss, i)) {
    165 			newsig = bsd_to_linux_sig[i];
    166 			if (newsig)
    167 				linux_sigaddset(lss, newsig);
    168 		}
    169 	}
    170 }
    171 
    172 /*
    173  * Convert between Linux and BSD sigaction structures. Linux has
    174  * one extra field (sa_restorer) which we don't support.
    175  */
    176 void
    177 linux_to_bsd_sigaction(lsa, bsa)
    178 	struct linux_sigaction *lsa;
    179 	struct sigaction *bsa;
    180 {
    181 
    182 	bsa->sa_handler = lsa->sa_handler;
    183 	linux_to_bsd_sigset(&bsa->sa_mask, &lsa->sa_mask);
    184 	bsa->sa_flags = 0;
    185 	if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
    186 		bsa->sa_flags |= SA_ONSTACK;
    187 	if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
    188 		bsa->sa_flags |= SA_RESTART;
    189 	if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
    190 		bsa->sa_flags |= SA_RESETHAND;
    191 	if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
    192 		bsa->sa_flags |= SA_NOCLDSTOP;
    193 	if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
    194 		bsa->sa_flags |= SA_NODEFER;
    195 }
    196 
    197 void
    198 bsd_to_linux_sigaction(bsa, lsa)
    199 	struct sigaction *bsa;
    200 	struct linux_sigaction *lsa;
    201 {
    202 
    203 	lsa->sa_handler = bsa->sa_handler;
    204 	bsd_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask);
    205 	lsa->sa_flags = 0;
    206 	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
    207 		lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
    208 	if ((bsa->sa_flags & SA_ONSTACK) != 0)
    209 		lsa->sa_flags |= LINUX_SA_ONSTACK;
    210 	if ((bsa->sa_flags & SA_RESTART) != 0)
    211 		lsa->sa_flags |= LINUX_SA_RESTART;
    212 	if ((bsa->sa_flags & SA_NODEFER) != 0)
    213 		lsa->sa_flags |= LINUX_SA_NOMASK;
    214 	if ((bsa->sa_flags & SA_RESETHAND) != 0)
    215 		lsa->sa_flags |= LINUX_SA_ONESHOT;
    216 	lsa->sa_restorer = NULL;
    217 }
    218 
    219 
    220 /*
    221  * The Linux sigaction() system call. Do the usual conversions,
    222  * and just call sigaction(). Some flags and values are silently
    223  * ignored (see above).
    224  */
    225 int
    226 linux_sigaction(p, uap, retval)
    227 	register struct proc *p;
    228 	struct linux_sigaction_args /* {
    229 		syscallarg(int) signum;
    230 		syscallarg(struct linux_sigaction *) nsa;
    231 		syscallarg(struct linux_sigaction *) osa;
    232 	} */ *uap;
    233 	register_t *retval;
    234 {
    235 	struct linux_sigaction *nlsa, *olsa, tmplsa;
    236 	struct sigaction *nbsa, *obsa, tmpbsa;
    237 	struct sigaction_args sa;
    238 	caddr_t sg;
    239 	int error;
    240 
    241 	sg = stackgap_init(p->p_emul);
    242 	nlsa = SCARG(uap, nsa);
    243 	olsa = SCARG(uap, osa);
    244 
    245 	if (olsa != NULL)
    246 		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
    247 	else
    248 		obsa = NULL;
    249 
    250 	if (nlsa != NULL) {
    251 		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
    252 		if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
    253 			return error;
    254 		linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
    255 		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
    256 			return error;
    257 	} else
    258 		nbsa = NULL;
    259 
    260 	SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
    261 	SCARG(&sa, nsa) = nbsa;
    262 	SCARG(&sa, osa) = obsa;
    263 
    264 	if ((error = sigaction(p, &sa, retval)) != 0)
    265 		return error;
    266 
    267 	if (olsa != NULL) {
    268 		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
    269 			return error;
    270 		bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
    271 		if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
    272 			return error;
    273 	}
    274 
    275 	return 0;
    276 }
    277 
    278 /*
    279  * The Linux signal() system call. I think that the signal() in the C
    280  * library actually calls sigaction, so I doubt this one is ever used.
    281  * But hey, it can't hurt having it here. The same restrictions as for
    282  * sigaction() apply.
    283  */
    284 int
    285 linux_signal(p, uap, retval)
    286 	register struct proc *p;
    287 	struct linux_signal_args /* {
    288 		syscallarg(int) sig;
    289 		syscallarg(linux_handler_t) handler;
    290 	} */ *uap;
    291 	register_t *retval;
    292 {
    293 	caddr_t sg;
    294 	struct sigaction_args sa_args;
    295 	struct sigaction *osa, *nsa, tmpsa;
    296 	int error;
    297 
    298 	sg = stackgap_init(p->p_emul);
    299 	nsa = stackgap_alloc(&sg, sizeof *nsa);
    300 	osa = stackgap_alloc(&sg, sizeof *osa);
    301 
    302 	tmpsa.sa_handler = SCARG(uap, handler);
    303 	tmpsa.sa_mask = (sigset_t) 0;
    304 	tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
    305 	if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
    306 		return error;
    307 
    308 	SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
    309 	SCARG(&sa_args, osa) = osa;
    310 	SCARG(&sa_args, nsa) = nsa;
    311 	if ((error = sigaction(p, &sa_args, retval)))
    312 		return error;
    313 
    314 	if ((error = copyin(osa, &tmpsa, sizeof *osa)))
    315 		return error;
    316 	retval[0] = (register_t) tmpsa.sa_handler;
    317 
    318 	return 0;
    319 }
    320 
    321 /*
    322  * This is just a copy of the svr4 compat one. I feel so creative now.
    323  */
    324 int
    325 linux_sigprocmask(p, uap, retval)
    326 	register struct proc *p;
    327 	struct linux_sigprocmask_args /* {
    328 		syscallarg(int) how;
    329 		syscallarg(linux_sigset_t *) set;
    330 		syscallarg(linux_sigset_t *) oset;
    331 	} */ *uap;
    332 	register_t *retval;
    333 {
    334 	linux_sigset_t ss;
    335 	sigset_t bs;
    336 	int error = 0;
    337 
    338 	*retval = 0;
    339 
    340 	if (SCARG(uap, oset) != NULL) {
    341 		/* Fix the return value first if needed */
    342 		bsd_to_linux_sigset(&p->p_sigmask, &ss);
    343 		if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
    344 			return error;
    345 	}
    346 
    347 	if (SCARG(uap, set) == NULL)
    348 		/* Just examine */
    349 		return 0;
    350 
    351 	if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
    352 		return error;
    353 
    354 	linux_to_bsd_sigset(&ss, &bs);
    355 
    356 	(void) splhigh();
    357 
    358 	switch (SCARG(uap, how)) {
    359 	case LINUX_SIG_BLOCK:
    360 		p->p_sigmask |= bs & ~sigcantmask;
    361 		break;
    362 
    363 	case LINUX_SIG_UNBLOCK:
    364 		p->p_sigmask &= ~bs;
    365 		break;
    366 
    367 	case LINUX_SIG_SETMASK:
    368 		p->p_sigmask = bs & ~sigcantmask;
    369 		break;
    370 
    371 	default:
    372 		error = EINVAL;
    373 		break;
    374 	}
    375 
    376 	(void) spl0();
    377 
    378 	return error;
    379 }
    380 
    381 /*
    382  * The functions below really make no distinction between an int
    383  * and [linux_]sigset_t. This is ok for now, but it might break
    384  * sometime. Then again, sigset_t is trusted to be an int everywhere
    385  * else in the kernel too.
    386  */
    387 /* ARGSUSED */
    388 int
    389 linux_siggetmask(p, uap, retval)
    390 	register struct proc *p;
    391 	void *uap;
    392 	register_t *retval;
    393 {
    394 
    395 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
    396 	return 0;
    397 }
    398 
    399 /*
    400  * The following three functions fiddle with a process' signal mask.
    401  * Convert the signal masks because of the different signal
    402  * values for Linux. The need for this is the reason why
    403  * they are here, and have not been mapped directly.
    404  */
    405 int
    406 linux_sigsetmask(p, uap, retval)
    407 	register struct proc *p;
    408 	struct linux_sigsetmask_args /* {
    409 		syscallarg(linux_sigset_t) mask;
    410 	} */ *uap;
    411 	register_t *retval;
    412 {
    413 	linux_sigset_t mask;
    414 	sigset_t bsdsig;
    415 
    416 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
    417 
    418 	mask = SCARG(uap, mask);
    419 	bsd_to_linux_sigset(&mask, &bsdsig);
    420 
    421 	splhigh();
    422 	p->p_sigmask = bsdsig & ~sigcantmask;
    423 	spl0();
    424 
    425 	return 0;
    426 }
    427 
    428 int
    429 linux_sigpending(p, uap, retval)
    430 	register struct proc *p;
    431 	struct linux_sigpending_args /* {
    432 		syscallarg(linux_sigset_t *) mask;
    433 	} */ *uap;
    434 	register_t *retval;
    435 {
    436 	sigset_t bs;
    437 	linux_sigset_t ls;
    438 
    439 	bs = p->p_siglist & p->p_sigmask;
    440 	bsd_to_linux_sigset(&bs, &ls);
    441 
    442 	return copyout(&ls, SCARG(uap, mask), sizeof(ls));
    443 }
    444 
    445 int
    446 linux_sigsuspend(p, uap, retval)
    447 	register struct proc *p;
    448 	struct linux_sigsuspend_args /* {
    449 		syscallarg(caddr_t) restart;
    450 		syscallarg(int) oldmask;
    451 		syscallarg(int) mask;
    452 	} */ *uap;
    453 	register_t *retval;
    454 {
    455 	struct sigsuspend_args sa;
    456 
    457 	linux_to_bsd_sigset(&SCARG(uap, mask), &SCARG(&sa, mask));
    458 	return sigsuspend(p, &sa, retval);
    459 }
    460 
    461 /*
    462  * The deprecated pause(2), which is really just an instance
    463  * of sigsuspend(2).
    464  */
    465 int
    466 linux_pause(p, uap, retval)
    467 	register struct proc *p;
    468 	void *uap;
    469 	register_t *retval;
    470 {
    471 	struct sigsuspend_args bsa;
    472 
    473 	SCARG(&bsa, mask) = p->p_sigmask;
    474 	return sigsuspend(p, &bsa, retval);
    475 }
    476 
    477 /*
    478  * Once more: only a signal conversion is needed.
    479  */
    480 int
    481 linux_kill(p, uap, retval)
    482 	register struct proc *p;
    483 	struct linux_kill_args /* {
    484 		syscallarg(int) pid;
    485 		syscallarg(int) signum;
    486 	} */ *uap;
    487 	register_t *retval;
    488 {
    489 	struct kill_args ka;
    490 
    491 	SCARG(&ka, pid) = SCARG(uap, pid);
    492 	SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
    493 	return kill(p, &ka, retval);
    494 }
    495