Home | History | Annotate | Line # | Download | only in common
linux_signal.c revision 1.13
      1 /*	$NetBSD: linux_signal.c,v 1.13 1998/09/29 14:15:49 tv 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	linux_sigmask(n)	(1 << ((n) - 1))
     56 #define	linux_sigemptyset(s)	memset((s), 0, sizeof(*(s)))
     57 #define	linux_sigismember(s, n)	(*(s) & linux_sigmask(n))
     58 #define	linux_sigaddset(s, n)	(*(s) |= linux_sigmask(n))
     59 
     60 int native_to_linux_sig[NSIG] = {
     61 	0,
     62 	LINUX_SIGHUP,
     63 	LINUX_SIGINT,
     64 	LINUX_SIGQUIT,
     65 	LINUX_SIGILL,
     66 	LINUX_SIGTRAP,
     67 	LINUX_SIGABRT,
     68 	0,			/* SIGEMT */
     69 	LINUX_SIGFPE,
     70 	LINUX_SIGKILL,
     71 	LINUX_SIGBUS,
     72 	LINUX_SIGSEGV,
     73 	0,			/* SIGSEGV */
     74 	LINUX_SIGPIPE,
     75 	LINUX_SIGALRM,
     76 	LINUX_SIGTERM,
     77 	LINUX_SIGURG,
     78 	LINUX_SIGSTOP,
     79 	LINUX_SIGTSTP,
     80 	LINUX_SIGCONT,
     81 	LINUX_SIGCHLD,
     82 	LINUX_SIGTTIN,
     83 	LINUX_SIGTTOU,
     84 	LINUX_SIGIO,
     85 	LINUX_SIGXCPU,
     86 	LINUX_SIGXFSZ,
     87 	LINUX_SIGVTALRM,
     88 	LINUX_SIGPROF,
     89 	LINUX_SIGWINCH,
     90 	0,			/* SIGINFO */
     91 	LINUX_SIGUSR1,
     92 	LINUX_SIGUSR2,
     93 	LINUX_SIGPWR,
     94 };
     95 
     96 int linux_to_native_sig[LINUX_NSIG] = {
     97 	0,
     98 	SIGHUP,
     99 	SIGINT,
    100 	SIGQUIT,
    101 	SIGILL,
    102 	SIGTRAP,
    103 	SIGABRT,
    104 	SIGBUS,
    105 	SIGFPE,
    106 	SIGKILL,
    107 	SIGUSR1,
    108 	SIGSEGV,
    109 	SIGUSR2,
    110 	SIGPIPE,
    111 	SIGALRM,
    112 	SIGTERM,
    113 	0,			/* SIGSTKFLT */
    114 	SIGCHLD,
    115 	SIGCONT,
    116 	SIGSTOP,
    117 	SIGTSTP,
    118 	SIGTTIN,
    119 	SIGTTOU,
    120 	SIGURG,
    121 	SIGXCPU,
    122 	SIGXFSZ,
    123 	SIGVTALRM,
    124 	SIGPROF,
    125 	SIGWINCH,
    126 	SIGIO,
    127 	SIGPWR,
    128 	0,			/* SIGUNUSED */
    129 };
    130 
    131 /* linux_signal.c */
    132 void linux_to_native_sigaction __P((struct linux_sigaction *, struct sigaction *));
    133 void native_to_linux_sigaction __P((struct sigaction *, struct linux_sigaction *));
    134 
    135 void
    136 linux_to_native_sigset(lss, bss)
    137 	const linux_sigset_t *lss;
    138 	sigset_t *bss;
    139 {
    140 	int i, newsig;
    141 
    142 	sigemptyset(bss);
    143 	for (i = 1; i < LINUX_NSIG; i++) {
    144 		if (linux_sigismember(lss, i)) {
    145 			newsig = linux_to_native_sig[i];
    146 			if (newsig)
    147 				sigaddset(bss, newsig);
    148 		}
    149 	}
    150 }
    151 
    152 void
    153 native_to_linux_sigset(bss, lss)
    154 	const sigset_t *bss;
    155 	linux_sigset_t *lss;
    156 {
    157 	int i, newsig;
    158 
    159 	linux_sigemptyset(lss);
    160 	for (i = 1; i < NSIG; i++) {
    161 		if (sigismember(bss, i)) {
    162 			newsig = native_to_linux_sig[i];
    163 			if (newsig)
    164 				linux_sigaddset(lss, newsig);
    165 		}
    166 	}
    167 }
    168 
    169 /*
    170  * Convert between Linux and BSD sigaction structures. Linux has
    171  * one extra field (sa_restorer) which we don't support.
    172  */
    173 void
    174 linux_to_native_sigaction(lsa, bsa)
    175 	struct linux_sigaction *lsa;
    176 	struct sigaction *bsa;
    177 {
    178 
    179 	bsa->sa_handler = lsa->sa_handler;
    180 	linux_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask);
    181 	bsa->sa_flags = 0;
    182 	if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
    183 		bsa->sa_flags |= SA_NOCLDSTOP;
    184 	if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
    185 		bsa->sa_flags |= SA_ONSTACK;
    186 	if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
    187 		bsa->sa_flags |= SA_RESTART;
    188 	if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
    189 		bsa->sa_flags |= SA_RESETHAND;
    190 	if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
    191 		bsa->sa_flags |= SA_NODEFER;
    192 #ifdef DEBUG
    193 	if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0)
    194 /*XXX*/		printf("linux_to_native_sigaction: extra bits ignored\n");
    195 	if (lsa->sa_restorer != 0)
    196 /*XXX*/		printf("linux_to_native_sigaction: sa_restorer ignored\n");
    197 #endif
    198 }
    199 
    200 void
    201 native_to_linux_sigaction(bsa, lsa)
    202 	struct sigaction *bsa;
    203 	struct linux_sigaction *lsa;
    204 {
    205 
    206 	lsa->sa_handler = bsa->sa_handler;
    207 	native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
    208 	lsa->sa_flags = 0;
    209 	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
    210 		lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
    211 	if ((bsa->sa_flags & SA_ONSTACK) != 0)
    212 		lsa->sa_flags |= LINUX_SA_ONSTACK;
    213 	if ((bsa->sa_flags & SA_RESTART) != 0)
    214 		lsa->sa_flags |= LINUX_SA_RESTART;
    215 	if ((bsa->sa_flags & SA_NODEFER) != 0)
    216 		lsa->sa_flags |= LINUX_SA_NOMASK;
    217 	if ((bsa->sa_flags & SA_RESETHAND) != 0)
    218 		lsa->sa_flags |= LINUX_SA_ONESHOT;
    219 	lsa->sa_restorer = NULL;
    220 }
    221 
    222 
    223 /*
    224  * The Linux sigaction() system call. Do the usual conversions,
    225  * and just call sigaction(). Some flags and values are silently
    226  * ignored (see above).
    227  */
    228 int
    229 linux_sys_sigaction(p, v, retval)
    230 	register struct proc *p;
    231 	void *v;
    232 	register_t *retval;
    233 {
    234 	struct linux_sys_sigaction_args /* {
    235 		syscallarg(int) signum;
    236 		syscallarg(const struct linux_sigaction *) nsa;
    237 		syscallarg(struct linux_sigaction *) osa;
    238 	} */ *uap = v;
    239 	struct linux_sigaction nlsa, olsa;
    240 	struct sigaction nbsa, obsa;
    241 	int error;
    242 
    243 	if (SCARG(uap, nsa)) {
    244 		error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
    245 		if (error)
    246 			return (error);
    247 		linux_to_native_sigaction(&nlsa, &nbsa);
    248 	}
    249 	error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)],
    250 	    SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0);
    251 	if (error)
    252 		return (error);
    253 	if (SCARG(uap, osa)) {
    254 		native_to_linux_sigaction(&obsa, &olsa);
    255 		error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
    256 		if (error)
    257 			return (error);
    258 	}
    259 	return (0);
    260 }
    261 
    262 /*
    263  * The Linux signal() system call. I think that the signal() in the C
    264  * library actually calls sigaction, so I doubt this one is ever used.
    265  * But hey, it can't hurt having it here. The same restrictions as for
    266  * sigaction() apply.
    267  */
    268 int
    269 linux_sys_signal(p, v, retval)
    270 	register struct proc *p;
    271 	void *v;
    272 	register_t *retval;
    273 {
    274 	struct linux_sys_signal_args /* {
    275 		syscallarg(int) sig;
    276 		syscallarg(linux_handler_t) handler;
    277 	} */ *uap = v;
    278 	struct sigaction nbsa, obsa;
    279 	int error;
    280 
    281 	nbsa.sa_handler = SCARG(uap, handler);
    282 	sigemptyset(&nbsa.sa_mask);
    283 	nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
    284 	error = sigaction1(p, linux_to_native_sig[SCARG(uap, sig)],
    285 	    &nbsa, &obsa);
    286 	if (error)
    287 		return (error);
    288 	*retval = (int)obsa.sa_handler;
    289 	return (0);
    290 }
    291 
    292 int
    293 linux_sys_sigprocmask(p, v, retval)
    294 	register struct proc *p;
    295 	void *v;
    296 	register_t *retval;
    297 {
    298 	struct linux_sys_sigprocmask_args /* {
    299 		syscallarg(int) how;
    300 		syscallarg(const linux_sigset_t *) set;
    301 		syscallarg(linux_sigset_t *) oset;
    302 	} */ *uap = v;
    303 	linux_sigset_t nlss, olss;
    304 	sigset_t nbss, obss;
    305 	int how;
    306 	int error;
    307 
    308 	switch (SCARG(uap, how)) {
    309 	case LINUX_SIG_BLOCK:
    310 		how = SIG_BLOCK;
    311 		break;
    312 	case LINUX_SIG_UNBLOCK:
    313 		how = SIG_UNBLOCK;
    314 		break;
    315 	case LINUX_SIG_SETMASK:
    316 		how = SIG_SETMASK;
    317 		break;
    318 	default:
    319 		return (EINVAL);
    320 	}
    321 
    322 	if (SCARG(uap, set)) {
    323 		error = copyin(SCARG(uap, set), &nlss, sizeof(nlss));
    324 		if (error)
    325 			return (error);
    326 		linux_to_native_sigset(&nlss, &nbss);
    327 	}
    328 	error = sigprocmask1(p, how,
    329 	    SCARG(uap, set) ? &nbss : 0, SCARG(uap, oset) ? &obss : 0);
    330 	if (error)
    331 		return (error);
    332 	if (SCARG(uap, oset)) {
    333 		native_to_linux_sigset(&obss, &olss);
    334 		error = copyout(&olss, SCARG(uap, oset), sizeof(olss));
    335 		if (error)
    336 			return (error);
    337 	}
    338 	return (error);
    339 }
    340 
    341 /* ARGSUSED */
    342 int
    343 linux_sys_siggetmask(p, v, retval)
    344 	register struct proc *p;
    345 	void *v;
    346 	register_t *retval;
    347 {
    348 	sigset_t bss;
    349 	linux_sigset_t lss;
    350 	int error;
    351 
    352 	error = sigprocmask1(p, SIG_SETMASK, 0, &bss);
    353 	if (error)
    354 		return (error);
    355 	native_to_linux_sigset(&bss, &lss);
    356 	*retval = lss;
    357 	return (0);
    358 }
    359 
    360 /*
    361  * The following three functions fiddle with a process' signal mask.
    362  * Convert the signal masks because of the different signal
    363  * values for Linux. The need for this is the reason why
    364  * they are here, and have not been mapped directly.
    365  */
    366 int
    367 linux_sys_sigsetmask(p, v, retval)
    368 	register struct proc *p;
    369 	void *v;
    370 	register_t *retval;
    371 {
    372 	struct linux_sys_sigsetmask_args /* {
    373 		syscallarg(linux_sigset_t) mask;
    374 	} */ *uap = v;
    375 	sigset_t nbss, obss;
    376 	linux_sigset_t nlss, olss;
    377 	int error;
    378 
    379 	nlss = SCARG(uap, mask);
    380 	linux_to_native_sigset(&nlss, &nbss);
    381 	error = sigprocmask1(p, SIG_SETMASK, &nbss, &obss);
    382 	if (error)
    383 		return (error);
    384 	native_to_linux_sigset(&obss, &olss);
    385 	*retval = olss;
    386 	return (0);
    387 }
    388 
    389 int
    390 linux_sys_sigpending(p, v, retval)
    391 	register struct proc *p;
    392 	void *v;
    393 	register_t *retval;
    394 {
    395 	struct linux_sys_sigpending_args /* {
    396 		syscallarg(linux_sigset_t *) set;
    397 	} */ *uap = v;
    398 	sigset_t bss;
    399 	linux_sigset_t lss;
    400 
    401 	sigpending1(p, &bss);
    402 	native_to_linux_sigset(&bss, &lss);
    403 	return copyout(&lss, SCARG(uap, set), sizeof(lss));
    404 }
    405 
    406 int
    407 linux_sys_sigsuspend(p, v, retval)
    408 	register struct proc *p;
    409 	void *v;
    410 	register_t *retval;
    411 {
    412 	struct linux_sys_sigsuspend_args /* {
    413 		syscallarg(caddr_t) restart;
    414 		syscallarg(int) oldmask;
    415 		syscallarg(int) mask;
    416 	} */ *uap = v;
    417 	linux_sigset_t lss;
    418 	sigset_t bss;
    419 
    420 	lss = SCARG(uap, mask);
    421 	linux_to_native_sigset(&lss, &bss);
    422 	return (sigsuspend1(p, &bss));
    423 }
    424 
    425 /*
    426  * The deprecated pause(2), which is really just an instance
    427  * of sigsuspend(2).
    428  */
    429 int
    430 linux_sys_pause(p, v, retval)
    431 	register struct proc *p;
    432 	void *v;
    433 	register_t *retval;
    434 {
    435 
    436 	return (sigsuspend1(p, 0));
    437 }
    438 
    439 /*
    440  * Once more: only a signal conversion is needed.
    441  */
    442 int
    443 linux_sys_kill(p, v, retval)
    444 	register struct proc *p;
    445 	void *v;
    446 	register_t *retval;
    447 {
    448 	struct linux_sys_kill_args /* {
    449 		syscallarg(int) pid;
    450 		syscallarg(int) signum;
    451 	} */ *uap = v;
    452 	struct sys_kill_args ka;
    453 
    454 	SCARG(&ka, pid) = SCARG(uap, pid);
    455 	SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)];
    456 	return sys_kill(p, &ka, retval);
    457 }
    458