Home | History | Annotate | Line # | Download | only in common
linux_signal.c revision 1.9
      1 /*	$NetBSD: linux_signal.c,v 1.9 1995/10/07 06:27:12 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_sys_sigaction(p, v, retval)
    227 	register struct proc *p;
    228 	void *v;
    229 	register_t *retval;
    230 {
    231 	struct linux_sys_sigaction_args /* {
    232 		syscallarg(int) signum;
    233 		syscallarg(struct linux_sigaction *) nsa;
    234 		syscallarg(struct linux_sigaction *) osa;
    235 	} */ *uap = v;
    236 	struct linux_sigaction *nlsa, *olsa, tmplsa;
    237 	struct sigaction *nbsa, *obsa, tmpbsa;
    238 	struct sys_sigaction_args sa;
    239 	caddr_t sg;
    240 	int error;
    241 
    242 	sg = stackgap_init(p->p_emul);
    243 	nlsa = SCARG(uap, nsa);
    244 	olsa = SCARG(uap, osa);
    245 
    246 	if (olsa != NULL)
    247 		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
    248 	else
    249 		obsa = NULL;
    250 
    251 	if (nlsa != NULL) {
    252 		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
    253 		if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
    254 			return error;
    255 		linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
    256 		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
    257 			return error;
    258 	} else
    259 		nbsa = NULL;
    260 
    261 	SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
    262 	SCARG(&sa, nsa) = nbsa;
    263 	SCARG(&sa, osa) = obsa;
    264 
    265 	if ((error = sys_sigaction(p, &sa, retval)) != 0)
    266 		return error;
    267 
    268 	if (olsa != NULL) {
    269 		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
    270 			return error;
    271 		bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
    272 		if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
    273 			return error;
    274 	}
    275 
    276 	return 0;
    277 }
    278 
    279 /*
    280  * The Linux signal() system call. I think that the signal() in the C
    281  * library actually calls sigaction, so I doubt this one is ever used.
    282  * But hey, it can't hurt having it here. The same restrictions as for
    283  * sigaction() apply.
    284  */
    285 int
    286 linux_sys_signal(p, v, retval)
    287 	register struct proc *p;
    288 	void *v;
    289 	register_t *retval;
    290 {
    291 	struct linux_sys_signal_args /* {
    292 		syscallarg(int) sig;
    293 		syscallarg(linux_handler_t) handler;
    294 	} */ *uap = v;
    295 	caddr_t sg;
    296 	struct sys_sigaction_args sa_args;
    297 	struct sigaction *osa, *nsa, tmpsa;
    298 	int error;
    299 
    300 	sg = stackgap_init(p->p_emul);
    301 	nsa = stackgap_alloc(&sg, sizeof *nsa);
    302 	osa = stackgap_alloc(&sg, sizeof *osa);
    303 
    304 	tmpsa.sa_handler = SCARG(uap, handler);
    305 	tmpsa.sa_mask = (sigset_t) 0;
    306 	tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
    307 	if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
    308 		return error;
    309 
    310 	SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
    311 	SCARG(&sa_args, osa) = osa;
    312 	SCARG(&sa_args, nsa) = nsa;
    313 	if ((error = sys_sigaction(p, &sa_args, retval)))
    314 		return error;
    315 
    316 	if ((error = copyin(osa, &tmpsa, sizeof *osa)))
    317 		return error;
    318 	retval[0] = (register_t) tmpsa.sa_handler;
    319 
    320 	return 0;
    321 }
    322 
    323 /*
    324  * This is just a copy of the svr4 compat one. I feel so creative now.
    325  */
    326 int
    327 linux_sys_sigprocmask(p, v, retval)
    328 	register struct proc *p;
    329 	void *v;
    330 	register_t *retval;
    331 {
    332 	struct linux_sys_sigprocmask_args /* {
    333 		syscallarg(int) how;
    334 		syscallarg(linux_sigset_t *) set;
    335 		syscallarg(linux_sigset_t *) oset;
    336 	} */ *uap = v;
    337 	linux_sigset_t ss;
    338 	sigset_t bs;
    339 	int error = 0;
    340 
    341 	*retval = 0;
    342 
    343 	if (SCARG(uap, oset) != NULL) {
    344 		/* Fix the return value first if needed */
    345 		bsd_to_linux_sigset(&p->p_sigmask, &ss);
    346 		if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
    347 			return error;
    348 	}
    349 
    350 	if (SCARG(uap, set) == NULL)
    351 		/* Just examine */
    352 		return 0;
    353 
    354 	if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
    355 		return error;
    356 
    357 	linux_to_bsd_sigset(&ss, &bs);
    358 
    359 	(void) splhigh();
    360 
    361 	switch (SCARG(uap, how)) {
    362 	case LINUX_SIG_BLOCK:
    363 		p->p_sigmask |= bs & ~sigcantmask;
    364 		break;
    365 
    366 	case LINUX_SIG_UNBLOCK:
    367 		p->p_sigmask &= ~bs;
    368 		break;
    369 
    370 	case LINUX_SIG_SETMASK:
    371 		p->p_sigmask = bs & ~sigcantmask;
    372 		break;
    373 
    374 	default:
    375 		error = EINVAL;
    376 		break;
    377 	}
    378 
    379 	(void) spl0();
    380 
    381 	return error;
    382 }
    383 
    384 /*
    385  * The functions below really make no distinction between an int
    386  * and [linux_]sigset_t. This is ok for now, but it might break
    387  * sometime. Then again, sigset_t is trusted to be an int everywhere
    388  * else in the kernel too.
    389  */
    390 /* ARGSUSED */
    391 int
    392 linux_sys_siggetmask(p, v, retval)
    393 	register struct proc *p;
    394 	void *v;
    395 	register_t *retval;
    396 {
    397 
    398 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
    399 	return 0;
    400 }
    401 
    402 /*
    403  * The following three functions fiddle with a process' signal mask.
    404  * Convert the signal masks because of the different signal
    405  * values for Linux. The need for this is the reason why
    406  * they are here, and have not been mapped directly.
    407  */
    408 int
    409 linux_sys_sigsetmask(p, v, retval)
    410 	register struct proc *p;
    411 	void *v;
    412 	register_t *retval;
    413 {
    414 	struct linux_sys_sigsetmask_args /* {
    415 		syscallarg(linux_sigset_t) mask;
    416 	} */ *uap = v;
    417 	linux_sigset_t mask;
    418 	sigset_t bsdsig;
    419 
    420 	bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
    421 
    422 	mask = SCARG(uap, mask);
    423 	bsd_to_linux_sigset(&mask, &bsdsig);
    424 
    425 	splhigh();
    426 	p->p_sigmask = bsdsig & ~sigcantmask;
    427 	spl0();
    428 
    429 	return 0;
    430 }
    431 
    432 int
    433 linux_sys_sigpending(p, v, retval)
    434 	register struct proc *p;
    435 	void *v;
    436 	register_t *retval;
    437 {
    438 	struct linux_sys_sigpending_args /* {
    439 		syscallarg(linux_sigset_t *) mask;
    440 	} */ *uap = v;
    441 	sigset_t bs;
    442 	linux_sigset_t ls;
    443 
    444 	bs = p->p_siglist & p->p_sigmask;
    445 	bsd_to_linux_sigset(&bs, &ls);
    446 
    447 	return copyout(&ls, SCARG(uap, mask), sizeof(ls));
    448 }
    449 
    450 int
    451 linux_sys_sigsuspend(p, v, retval)
    452 	register struct proc *p;
    453 	void *v;
    454 	register_t *retval;
    455 {
    456 	struct linux_sys_sigsuspend_args /* {
    457 		syscallarg(caddr_t) restart;
    458 		syscallarg(int) oldmask;
    459 		syscallarg(int) mask;
    460 	} */ *uap = v;
    461 	struct sys_sigsuspend_args sa;
    462 
    463 	linux_to_bsd_sigset(&SCARG(uap, mask), &SCARG(&sa, mask));
    464 	return sys_sigsuspend(p, &sa, retval);
    465 }
    466 
    467 /*
    468  * The deprecated pause(2), which is really just an instance
    469  * of sigsuspend(2).
    470  */
    471 int
    472 linux_sys_pause(p, v, retval)
    473 	register struct proc *p;
    474 	void *v;
    475 	register_t *retval;
    476 {
    477 	struct sys_sigsuspend_args bsa;
    478 
    479 	SCARG(&bsa, mask) = p->p_sigmask;
    480 	return sys_sigsuspend(p, &bsa, retval);
    481 }
    482 
    483 /*
    484  * Once more: only a signal conversion is needed.
    485  */
    486 int
    487 linux_sys_kill(p, v, retval)
    488 	register struct proc *p;
    489 	void *v;
    490 	register_t *retval;
    491 {
    492 	struct linux_sys_kill_args /* {
    493 		syscallarg(int) pid;
    494 		syscallarg(int) signum;
    495 	} */ *uap = v;
    496 	struct sys_kill_args ka;
    497 
    498 	SCARG(&ka, pid) = SCARG(uap, pid);
    499 	SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
    500 	return sys_kill(p, &ka, retval);
    501 }
    502