Home | History | Annotate | Line # | Download | only in common
linux_signal.c revision 1.12
      1 /*	$NetBSD: linux_signal.c,v 1.12 1998/09/11 12:50:09 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	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 	if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0)
    193 /*XXX*/		printf("linux_to_native_sigaction: extra bits ignored\n");
    194 	if (lsa->sa_restorer != 0)
    195 /*XXX*/		printf("linux_to_native_sigaction: sa_restorer ignored\n");
    196 }
    197 
    198 void
    199 native_to_linux_sigaction(bsa, lsa)
    200 	struct sigaction *bsa;
    201 	struct linux_sigaction *lsa;
    202 {
    203 
    204 	lsa->sa_handler = bsa->sa_handler;
    205 	native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
    206 	lsa->sa_flags = 0;
    207 	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
    208 		lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
    209 	if ((bsa->sa_flags & SA_ONSTACK) != 0)
    210 		lsa->sa_flags |= LINUX_SA_ONSTACK;
    211 	if ((bsa->sa_flags & SA_RESTART) != 0)
    212 		lsa->sa_flags |= LINUX_SA_RESTART;
    213 	if ((bsa->sa_flags & SA_NODEFER) != 0)
    214 		lsa->sa_flags |= LINUX_SA_NOMASK;
    215 	if ((bsa->sa_flags & SA_RESETHAND) != 0)
    216 		lsa->sa_flags |= LINUX_SA_ONESHOT;
    217 	lsa->sa_restorer = NULL;
    218 }
    219 
    220 
    221 /*
    222  * The Linux sigaction() system call. Do the usual conversions,
    223  * and just call sigaction(). Some flags and values are silently
    224  * ignored (see above).
    225  */
    226 int
    227 linux_sys_sigaction(p, v, retval)
    228 	register struct proc *p;
    229 	void *v;
    230 	register_t *retval;
    231 {
    232 	struct linux_sys_sigaction_args /* {
    233 		syscallarg(int) signum;
    234 		syscallarg(const struct linux_sigaction *) nsa;
    235 		syscallarg(struct linux_sigaction *) osa;
    236 	} */ *uap = v;
    237 	struct linux_sigaction nlsa, olsa;
    238 	struct sigaction nbsa, obsa;
    239 	int error;
    240 
    241 	if (SCARG(uap, nsa)) {
    242 		error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa));
    243 		if (error)
    244 			return (error);
    245 		linux_to_native_sigaction(&nlsa, &nbsa);
    246 	}
    247 	error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)],
    248 	    SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0);
    249 	if (error)
    250 		return (error);
    251 	if (SCARG(uap, osa)) {
    252 		native_to_linux_sigaction(&obsa, &olsa);
    253 		error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa));
    254 		if (error)
    255 			return (error);
    256 	}
    257 	return (0);
    258 }
    259 
    260 /*
    261  * The Linux signal() system call. I think that the signal() in the C
    262  * library actually calls sigaction, so I doubt this one is ever used.
    263  * But hey, it can't hurt having it here. The same restrictions as for
    264  * sigaction() apply.
    265  */
    266 int
    267 linux_sys_signal(p, v, retval)
    268 	register struct proc *p;
    269 	void *v;
    270 	register_t *retval;
    271 {
    272 	struct linux_sys_signal_args /* {
    273 		syscallarg(int) sig;
    274 		syscallarg(linux_handler_t) handler;
    275 	} */ *uap = v;
    276 	struct sigaction nbsa, obsa;
    277 	int error;
    278 
    279 	nbsa.sa_handler = SCARG(uap, handler);
    280 	sigemptyset(&nbsa.sa_mask);
    281 	nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
    282 	error = sigaction1(p, linux_to_native_sig[SCARG(uap, sig)],
    283 	    &nbsa, &obsa);
    284 	if (error)
    285 		return (error);
    286 	*retval = (int)obsa.sa_handler;
    287 	return (0);
    288 }
    289 
    290 int
    291 linux_sys_sigprocmask(p, v, retval)
    292 	register struct proc *p;
    293 	void *v;
    294 	register_t *retval;
    295 {
    296 	struct linux_sys_sigprocmask_args /* {
    297 		syscallarg(int) how;
    298 		syscallarg(const linux_sigset_t *) set;
    299 		syscallarg(linux_sigset_t *) oset;
    300 	} */ *uap = v;
    301 	linux_sigset_t nlss, olss;
    302 	sigset_t nbss, obss;
    303 	int how;
    304 	int error;
    305 
    306 	switch (SCARG(uap, how)) {
    307 	case LINUX_SIG_BLOCK:
    308 		how = SIG_BLOCK;
    309 		break;
    310 	case LINUX_SIG_UNBLOCK:
    311 		how = SIG_UNBLOCK;
    312 		break;
    313 	case LINUX_SIG_SETMASK:
    314 		how = SIG_SETMASK;
    315 		break;
    316 	default:
    317 		return (EINVAL);
    318 	}
    319 
    320 	if (SCARG(uap, set)) {
    321 		error = copyin(SCARG(uap, set), &nlss, sizeof(nlss));
    322 		if (error)
    323 			return (error);
    324 		linux_to_native_sigset(&nlss, &nbss);
    325 	}
    326 	error = sigprocmask1(p, how,
    327 	    SCARG(uap, set) ? &nbss : 0, SCARG(uap, oset) ? &obss : 0);
    328 	if (error)
    329 		return (error);
    330 	if (SCARG(uap, oset)) {
    331 		native_to_linux_sigset(&obss, &olss);
    332 		error = copyout(&olss, SCARG(uap, oset), sizeof(olss));
    333 		if (error)
    334 			return (error);
    335 	}
    336 	return (error);
    337 }
    338 
    339 /* ARGSUSED */
    340 int
    341 linux_sys_siggetmask(p, v, retval)
    342 	register struct proc *p;
    343 	void *v;
    344 	register_t *retval;
    345 {
    346 	sigset_t bss;
    347 	linux_sigset_t lss;
    348 	int error;
    349 
    350 	error = sigprocmask1(p, SIG_SETMASK, 0, &bss);
    351 	if (error)
    352 		return (error);
    353 	native_to_linux_sigset(&bss, &lss);
    354 	*retval = lss;
    355 	return (0);
    356 }
    357 
    358 /*
    359  * The following three functions fiddle with a process' signal mask.
    360  * Convert the signal masks because of the different signal
    361  * values for Linux. The need for this is the reason why
    362  * they are here, and have not been mapped directly.
    363  */
    364 int
    365 linux_sys_sigsetmask(p, v, retval)
    366 	register struct proc *p;
    367 	void *v;
    368 	register_t *retval;
    369 {
    370 	struct linux_sys_sigsetmask_args /* {
    371 		syscallarg(linux_sigset_t) mask;
    372 	} */ *uap = v;
    373 	sigset_t nbss, obss;
    374 	linux_sigset_t nlss, olss;
    375 	int error;
    376 
    377 	nlss = SCARG(uap, mask);
    378 	linux_to_native_sigset(&nlss, &nbss);
    379 	error = sigprocmask1(p, SIG_SETMASK, &nbss, &obss);
    380 	if (error)
    381 		return (error);
    382 	native_to_linux_sigset(&obss, &olss);
    383 	*retval = olss;
    384 	return (0);
    385 }
    386 
    387 int
    388 linux_sys_sigpending(p, v, retval)
    389 	register struct proc *p;
    390 	void *v;
    391 	register_t *retval;
    392 {
    393 	struct linux_sys_sigpending_args /* {
    394 		syscallarg(linux_sigset_t *) set;
    395 	} */ *uap = v;
    396 	sigset_t bss;
    397 	linux_sigset_t lss;
    398 
    399 	sigpending1(p, &bss);
    400 	native_to_linux_sigset(&bss, &lss);
    401 	return copyout(&lss, SCARG(uap, set), sizeof(lss));
    402 }
    403 
    404 int
    405 linux_sys_sigsuspend(p, v, retval)
    406 	register struct proc *p;
    407 	void *v;
    408 	register_t *retval;
    409 {
    410 	struct linux_sys_sigsuspend_args /* {
    411 		syscallarg(caddr_t) restart;
    412 		syscallarg(int) oldmask;
    413 		syscallarg(int) mask;
    414 	} */ *uap = v;
    415 	linux_sigset_t lss;
    416 	sigset_t bss;
    417 
    418 	lss = SCARG(uap, mask);
    419 	linux_to_native_sigset(&lss, &bss);
    420 	return (sigsuspend1(p, &bss));
    421 }
    422 
    423 /*
    424  * The deprecated pause(2), which is really just an instance
    425  * of sigsuspend(2).
    426  */
    427 int
    428 linux_sys_pause(p, v, retval)
    429 	register struct proc *p;
    430 	void *v;
    431 	register_t *retval;
    432 {
    433 
    434 	return (sigsuspend1(p, 0));
    435 }
    436 
    437 /*
    438  * Once more: only a signal conversion is needed.
    439  */
    440 int
    441 linux_sys_kill(p, v, retval)
    442 	register struct proc *p;
    443 	void *v;
    444 	register_t *retval;
    445 {
    446 	struct linux_sys_kill_args /* {
    447 		syscallarg(int) pid;
    448 		syscallarg(int) signum;
    449 	} */ *uap = v;
    450 	struct sys_kill_args ka;
    451 
    452 	SCARG(&ka, pid) = SCARG(uap, pid);
    453 	SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)];
    454 	return sys_kill(p, &ka, retval);
    455 }
    456