linux_sigarray.c revision 1.12
11.12Smycroft/* $NetBSD: linux_sigarray.c,v 1.12 1998/09/11 12:50:09 mycroft Exp $ */ 21.1Sfvdl 31.1Sfvdl/* 41.1Sfvdl * Copyright (c) 1995 Frank van der Linden 51.1Sfvdl * All rights reserved. 61.1Sfvdl * 71.1Sfvdl * Redistribution and use in source and binary forms, with or without 81.1Sfvdl * modification, are permitted provided that the following conditions 91.1Sfvdl * are met: 101.1Sfvdl * 1. Redistributions of source code must retain the above copyright 111.1Sfvdl * notice, this list of conditions and the following disclaimer. 121.1Sfvdl * 2. Redistributions in binary form must reproduce the above copyright 131.1Sfvdl * notice, this list of conditions and the following disclaimer in the 141.1Sfvdl * documentation and/or other materials provided with the distribution. 151.1Sfvdl * 3. All advertising materials mentioning features or use of this software 161.1Sfvdl * must display the following acknowledgement: 171.1Sfvdl * This product includes software developed for the NetBSD Project 181.1Sfvdl * by Frank van der Linden 191.1Sfvdl * 4. The name of the author may not be used to endorse or promote products 201.1Sfvdl * derived from this software without specific prior written permission 211.1Sfvdl * 221.1Sfvdl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 231.1Sfvdl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 241.1Sfvdl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 251.1Sfvdl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 261.1Sfvdl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 271.1Sfvdl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 281.1Sfvdl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 291.1Sfvdl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 301.1Sfvdl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 311.1Sfvdl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 321.1Sfvdl * 331.1Sfvdl * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp 341.1Sfvdl */ 351.1Sfvdl 361.1Sfvdl#include <sys/param.h> 371.1Sfvdl#include <sys/systm.h> 381.1Sfvdl#include <sys/namei.h> 391.1Sfvdl#include <sys/proc.h> 401.1Sfvdl#include <sys/filedesc.h> 411.1Sfvdl#include <sys/ioctl.h> 421.1Sfvdl#include <sys/mount.h> 431.1Sfvdl#include <sys/kernel.h> 441.1Sfvdl#include <sys/signal.h> 451.1Sfvdl#include <sys/signalvar.h> 461.1Sfvdl#include <sys/malloc.h> 471.1Sfvdl 481.1Sfvdl#include <sys/syscallargs.h> 491.1Sfvdl 501.1Sfvdl#include <compat/linux/linux_types.h> 511.7Smycroft#include <compat/linux/linux_signal.h> 521.1Sfvdl#include <compat/linux/linux_syscallargs.h> 531.1Sfvdl#include <compat/linux/linux_util.h> 541.1Sfvdl 551.6Smycroft#define linux_sigmask(n) (1 << ((n) - 1)) 561.11Sperry#define linux_sigemptyset(s) memset((s), 0, sizeof(*(s))) 571.6Smycroft#define linux_sigismember(s, n) (*(s) & linux_sigmask(n)) 581.6Smycroft#define linux_sigaddset(s, n) (*(s) |= linux_sigmask(n)) 591.6Smycroft 601.12Smycroftint native_to_linux_sig[NSIG] = { 611.6Smycroft 0, 621.6Smycroft LINUX_SIGHUP, 631.6Smycroft LINUX_SIGINT, 641.6Smycroft LINUX_SIGQUIT, 651.6Smycroft LINUX_SIGILL, 661.6Smycroft LINUX_SIGTRAP, 671.6Smycroft LINUX_SIGABRT, 681.12Smycroft 0, /* SIGEMT */ 691.6Smycroft LINUX_SIGFPE, 701.6Smycroft LINUX_SIGKILL, 711.6Smycroft LINUX_SIGBUS, 721.6Smycroft LINUX_SIGSEGV, 731.12Smycroft 0, /* SIGSEGV */ 741.6Smycroft LINUX_SIGPIPE, 751.6Smycroft LINUX_SIGALRM, 761.6Smycroft LINUX_SIGTERM, 771.6Smycroft LINUX_SIGURG, 781.6Smycroft LINUX_SIGSTOP, 791.6Smycroft LINUX_SIGTSTP, 801.6Smycroft LINUX_SIGCONT, 811.6Smycroft LINUX_SIGCHLD, 821.6Smycroft LINUX_SIGTTIN, 831.6Smycroft LINUX_SIGTTOU, 841.6Smycroft LINUX_SIGIO, 851.6Smycroft LINUX_SIGXCPU, 861.6Smycroft LINUX_SIGXFSZ, 871.6Smycroft LINUX_SIGVTALRM, 881.6Smycroft LINUX_SIGPROF, 891.6Smycroft LINUX_SIGWINCH, 901.12Smycroft 0, /* SIGINFO */ 911.6Smycroft LINUX_SIGUSR1, 921.6Smycroft LINUX_SIGUSR2, 931.12Smycroft LINUX_SIGPWR, 941.6Smycroft}; 951.6Smycroft 961.12Smycroftint linux_to_native_sig[LINUX_NSIG] = { 971.6Smycroft 0, 981.6Smycroft SIGHUP, 991.6Smycroft SIGINT, 1001.6Smycroft SIGQUIT, 1011.6Smycroft SIGILL, 1021.6Smycroft SIGTRAP, 1031.6Smycroft SIGABRT, 1041.6Smycroft SIGBUS, 1051.6Smycroft SIGFPE, 1061.6Smycroft SIGKILL, 1071.6Smycroft SIGUSR1, 1081.6Smycroft SIGSEGV, 1091.6Smycroft SIGUSR2, 1101.6Smycroft SIGPIPE, 1111.6Smycroft SIGALRM, 1121.6Smycroft SIGTERM, 1131.12Smycroft 0, /* SIGSTKFLT */ 1141.6Smycroft SIGCHLD, 1151.6Smycroft SIGCONT, 1161.6Smycroft SIGSTOP, 1171.6Smycroft SIGTSTP, 1181.6Smycroft SIGTTIN, 1191.6Smycroft SIGTTOU, 1201.6Smycroft SIGURG, 1211.6Smycroft SIGXCPU, 1221.6Smycroft SIGXFSZ, 1231.6Smycroft SIGVTALRM, 1241.6Smycroft SIGPROF, 1251.6Smycroft SIGWINCH, 1261.6Smycroft SIGIO, 1271.12Smycroft SIGPWR, 1281.12Smycroft 0, /* SIGUNUSED */ 1291.6Smycroft}; 1301.1Sfvdl 1311.10Schristos/* linux_signal.c */ 1321.12Smycroftvoid linux_to_native_sigaction __P((struct linux_sigaction *, struct sigaction *)); 1331.12Smycroftvoid native_to_linux_sigaction __P((struct sigaction *, struct linux_sigaction *)); 1341.10Schristos 1351.6Smycroftvoid 1361.12Smycroftlinux_to_native_sigset(lss, bss) 1371.1Sfvdl const linux_sigset_t *lss; 1381.1Sfvdl sigset_t *bss; 1391.1Sfvdl{ 1401.1Sfvdl int i, newsig; 1411.1Sfvdl 1421.6Smycroft sigemptyset(bss); 1431.6Smycroft for (i = 1; i < LINUX_NSIG; i++) { 1441.6Smycroft if (linux_sigismember(lss, i)) { 1451.12Smycroft newsig = linux_to_native_sig[i]; 1461.1Sfvdl if (newsig) 1471.6Smycroft sigaddset(bss, newsig); 1481.1Sfvdl } 1491.1Sfvdl } 1501.1Sfvdl} 1511.1Sfvdl 1521.1Sfvdlvoid 1531.12Smycroftnative_to_linux_sigset(bss, lss) 1541.1Sfvdl const sigset_t *bss; 1551.1Sfvdl linux_sigset_t *lss; 1561.1Sfvdl{ 1571.1Sfvdl int i, newsig; 1581.1Sfvdl 1591.6Smycroft linux_sigemptyset(lss); 1601.6Smycroft for (i = 1; i < NSIG; i++) { 1611.6Smycroft if (sigismember(bss, i)) { 1621.12Smycroft newsig = native_to_linux_sig[i]; 1631.1Sfvdl if (newsig) 1641.6Smycroft linux_sigaddset(lss, newsig); 1651.1Sfvdl } 1661.1Sfvdl } 1671.1Sfvdl} 1681.1Sfvdl 1691.1Sfvdl/* 1701.1Sfvdl * Convert between Linux and BSD sigaction structures. Linux has 1711.6Smycroft * one extra field (sa_restorer) which we don't support. 1721.1Sfvdl */ 1731.1Sfvdlvoid 1741.12Smycroftlinux_to_native_sigaction(lsa, bsa) 1751.1Sfvdl struct linux_sigaction *lsa; 1761.1Sfvdl struct sigaction *bsa; 1771.1Sfvdl{ 1781.6Smycroft 1791.1Sfvdl bsa->sa_handler = lsa->sa_handler; 1801.12Smycroft linux_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask); 1811.1Sfvdl bsa->sa_flags = 0; 1821.12Smycroft if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0) 1831.12Smycroft bsa->sa_flags |= SA_NOCLDSTOP; 1841.6Smycroft if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0) 1851.6Smycroft bsa->sa_flags |= SA_ONSTACK; 1861.6Smycroft if ((lsa->sa_flags & LINUX_SA_RESTART) != 0) 1871.6Smycroft bsa->sa_flags |= SA_RESTART; 1881.6Smycroft if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0) 1891.6Smycroft bsa->sa_flags |= SA_RESETHAND; 1901.6Smycroft if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0) 1911.6Smycroft bsa->sa_flags |= SA_NODEFER; 1921.12Smycroft if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0) 1931.12Smycroft/*XXX*/ printf("linux_to_native_sigaction: extra bits ignored\n"); 1941.12Smycroft if (lsa->sa_restorer != 0) 1951.12Smycroft/*XXX*/ printf("linux_to_native_sigaction: sa_restorer ignored\n"); 1961.1Sfvdl} 1971.1Sfvdl 1981.1Sfvdlvoid 1991.12Smycroftnative_to_linux_sigaction(bsa, lsa) 2001.1Sfvdl struct sigaction *bsa; 2011.1Sfvdl struct linux_sigaction *lsa; 2021.1Sfvdl{ 2031.6Smycroft 2041.1Sfvdl lsa->sa_handler = bsa->sa_handler; 2051.12Smycroft native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask); 2061.1Sfvdl lsa->sa_flags = 0; 2071.6Smycroft if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 2081.6Smycroft lsa->sa_flags |= LINUX_SA_NOCLDSTOP; 2091.6Smycroft if ((bsa->sa_flags & SA_ONSTACK) != 0) 2101.6Smycroft lsa->sa_flags |= LINUX_SA_ONSTACK; 2111.6Smycroft if ((bsa->sa_flags & SA_RESTART) != 0) 2121.6Smycroft lsa->sa_flags |= LINUX_SA_RESTART; 2131.6Smycroft if ((bsa->sa_flags & SA_NODEFER) != 0) 2141.6Smycroft lsa->sa_flags |= LINUX_SA_NOMASK; 2151.6Smycroft if ((bsa->sa_flags & SA_RESETHAND) != 0) 2161.6Smycroft lsa->sa_flags |= LINUX_SA_ONESHOT; 2171.1Sfvdl lsa->sa_restorer = NULL; 2181.1Sfvdl} 2191.1Sfvdl 2201.1Sfvdl 2211.1Sfvdl/* 2221.1Sfvdl * The Linux sigaction() system call. Do the usual conversions, 2231.1Sfvdl * and just call sigaction(). Some flags and values are silently 2241.1Sfvdl * ignored (see above). 2251.1Sfvdl */ 2261.1Sfvdlint 2271.9Smycroftlinux_sys_sigaction(p, v, retval) 2281.1Sfvdl register struct proc *p; 2291.8Sthorpej void *v; 2301.8Sthorpej register_t *retval; 2311.8Sthorpej{ 2321.9Smycroft struct linux_sys_sigaction_args /* { 2331.1Sfvdl syscallarg(int) signum; 2341.12Smycroft syscallarg(const struct linux_sigaction *) nsa; 2351.1Sfvdl syscallarg(struct linux_sigaction *) osa; 2361.8Sthorpej } */ *uap = v; 2371.12Smycroft struct linux_sigaction nlsa, olsa; 2381.12Smycroft struct sigaction nbsa, obsa; 2391.1Sfvdl int error; 2401.1Sfvdl 2411.12Smycroft if (SCARG(uap, nsa)) { 2421.12Smycroft error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 2431.12Smycroft if (error) 2441.12Smycroft return (error); 2451.12Smycroft linux_to_native_sigaction(&nlsa, &nbsa); 2461.12Smycroft } 2471.12Smycroft error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)], 2481.12Smycroft SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0); 2491.12Smycroft if (error) 2501.12Smycroft return (error); 2511.12Smycroft if (SCARG(uap, osa)) { 2521.12Smycroft native_to_linux_sigaction(&obsa, &olsa); 2531.12Smycroft error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 2541.12Smycroft if (error) 2551.12Smycroft return (error); 2561.1Sfvdl } 2571.12Smycroft return (0); 2581.1Sfvdl} 2591.1Sfvdl 2601.1Sfvdl/* 2611.1Sfvdl * The Linux signal() system call. I think that the signal() in the C 2621.1Sfvdl * library actually calls sigaction, so I doubt this one is ever used. 2631.1Sfvdl * But hey, it can't hurt having it here. The same restrictions as for 2641.1Sfvdl * sigaction() apply. 2651.1Sfvdl */ 2661.1Sfvdlint 2671.9Smycroftlinux_sys_signal(p, v, retval) 2681.1Sfvdl register struct proc *p; 2691.8Sthorpej void *v; 2701.8Sthorpej register_t *retval; 2711.8Sthorpej{ 2721.9Smycroft struct linux_sys_signal_args /* { 2731.1Sfvdl syscallarg(int) sig; 2741.1Sfvdl syscallarg(linux_handler_t) handler; 2751.8Sthorpej } */ *uap = v; 2761.12Smycroft struct sigaction nbsa, obsa; 2771.1Sfvdl int error; 2781.1Sfvdl 2791.12Smycroft nbsa.sa_handler = SCARG(uap, handler); 2801.12Smycroft sigemptyset(&nbsa.sa_mask); 2811.12Smycroft nbsa.sa_flags = SA_RESETHAND | SA_NODEFER; 2821.12Smycroft error = sigaction1(p, linux_to_native_sig[SCARG(uap, sig)], 2831.12Smycroft &nbsa, &obsa); 2841.12Smycroft if (error) 2851.12Smycroft return (error); 2861.12Smycroft *retval = (int)obsa.sa_handler; 2871.12Smycroft return (0); 2881.1Sfvdl} 2891.1Sfvdl 2901.1Sfvdlint 2911.9Smycroftlinux_sys_sigprocmask(p, v, retval) 2921.1Sfvdl register struct proc *p; 2931.8Sthorpej void *v; 2941.8Sthorpej register_t *retval; 2951.8Sthorpej{ 2961.9Smycroft struct linux_sys_sigprocmask_args /* { 2971.1Sfvdl syscallarg(int) how; 2981.12Smycroft syscallarg(const linux_sigset_t *) set; 2991.6Smycroft syscallarg(linux_sigset_t *) oset; 3001.8Sthorpej } */ *uap = v; 3011.12Smycroft linux_sigset_t nlss, olss; 3021.12Smycroft sigset_t nbss, obss; 3031.12Smycroft int how; 3041.12Smycroft int error; 3051.1Sfvdl 3061.1Sfvdl switch (SCARG(uap, how)) { 3071.1Sfvdl case LINUX_SIG_BLOCK: 3081.12Smycroft how = SIG_BLOCK; 3091.1Sfvdl break; 3101.1Sfvdl case LINUX_SIG_UNBLOCK: 3111.12Smycroft how = SIG_UNBLOCK; 3121.1Sfvdl break; 3131.1Sfvdl case LINUX_SIG_SETMASK: 3141.12Smycroft how = SIG_SETMASK; 3151.1Sfvdl break; 3161.1Sfvdl default: 3171.12Smycroft return (EINVAL); 3181.1Sfvdl } 3191.1Sfvdl 3201.12Smycroft if (SCARG(uap, set)) { 3211.12Smycroft error = copyin(SCARG(uap, set), &nlss, sizeof(nlss)); 3221.12Smycroft if (error) 3231.12Smycroft return (error); 3241.12Smycroft linux_to_native_sigset(&nlss, &nbss); 3251.12Smycroft } 3261.12Smycroft error = sigprocmask1(p, how, 3271.12Smycroft SCARG(uap, set) ? &nbss : 0, SCARG(uap, oset) ? &obss : 0); 3281.12Smycroft if (error) 3291.12Smycroft return (error); 3301.12Smycroft if (SCARG(uap, oset)) { 3311.12Smycroft native_to_linux_sigset(&obss, &olss); 3321.12Smycroft error = copyout(&olss, SCARG(uap, oset), sizeof(olss)); 3331.12Smycroft if (error) 3341.12Smycroft return (error); 3351.12Smycroft } 3361.12Smycroft return (error); 3371.1Sfvdl} 3381.1Sfvdl 3391.1Sfvdl/* ARGSUSED */ 3401.1Sfvdlint 3411.9Smycroftlinux_sys_siggetmask(p, v, retval) 3421.6Smycroft register struct proc *p; 3431.9Smycroft void *v; 3441.1Sfvdl register_t *retval; 3451.1Sfvdl{ 3461.12Smycroft sigset_t bss; 3471.12Smycroft linux_sigset_t lss; 3481.12Smycroft int error; 3491.6Smycroft 3501.12Smycroft error = sigprocmask1(p, SIG_SETMASK, 0, &bss); 3511.12Smycroft if (error) 3521.12Smycroft return (error); 3531.12Smycroft native_to_linux_sigset(&bss, &lss); 3541.12Smycroft *retval = lss; 3551.12Smycroft return (0); 3561.1Sfvdl} 3571.1Sfvdl 3581.1Sfvdl/* 3591.1Sfvdl * The following three functions fiddle with a process' signal mask. 3601.1Sfvdl * Convert the signal masks because of the different signal 3611.1Sfvdl * values for Linux. The need for this is the reason why 3621.1Sfvdl * they are here, and have not been mapped directly. 3631.1Sfvdl */ 3641.1Sfvdlint 3651.9Smycroftlinux_sys_sigsetmask(p, v, retval) 3661.6Smycroft register struct proc *p; 3671.8Sthorpej void *v; 3681.8Sthorpej register_t *retval; 3691.8Sthorpej{ 3701.9Smycroft struct linux_sys_sigsetmask_args /* { 3711.1Sfvdl syscallarg(linux_sigset_t) mask; 3721.8Sthorpej } */ *uap = v; 3731.12Smycroft sigset_t nbss, obss; 3741.12Smycroft linux_sigset_t nlss, olss; 3751.12Smycroft int error; 3761.1Sfvdl 3771.12Smycroft nlss = SCARG(uap, mask); 3781.12Smycroft linux_to_native_sigset(&nlss, &nbss); 3791.12Smycroft error = sigprocmask1(p, SIG_SETMASK, &nbss, &obss); 3801.12Smycroft if (error) 3811.12Smycroft return (error); 3821.12Smycroft native_to_linux_sigset(&obss, &olss); 3831.12Smycroft *retval = olss; 3841.12Smycroft return (0); 3851.1Sfvdl} 3861.1Sfvdl 3871.1Sfvdlint 3881.9Smycroftlinux_sys_sigpending(p, v, retval) 3891.6Smycroft register struct proc *p; 3901.8Sthorpej void *v; 3911.8Sthorpej register_t *retval; 3921.8Sthorpej{ 3931.9Smycroft struct linux_sys_sigpending_args /* { 3941.12Smycroft syscallarg(linux_sigset_t *) set; 3951.8Sthorpej } */ *uap = v; 3961.12Smycroft sigset_t bss; 3971.12Smycroft linux_sigset_t lss; 3981.1Sfvdl 3991.12Smycroft sigpending1(p, &bss); 4001.12Smycroft native_to_linux_sigset(&bss, &lss); 4011.12Smycroft return copyout(&lss, SCARG(uap, set), sizeof(lss)); 4021.1Sfvdl} 4031.1Sfvdl 4041.1Sfvdlint 4051.9Smycroftlinux_sys_sigsuspend(p, v, retval) 4061.6Smycroft register struct proc *p; 4071.8Sthorpej void *v; 4081.8Sthorpej register_t *retval; 4091.8Sthorpej{ 4101.9Smycroft struct linux_sys_sigsuspend_args /* { 4111.3Sfvdl syscallarg(caddr_t) restart; 4121.3Sfvdl syscallarg(int) oldmask; 4131.1Sfvdl syscallarg(int) mask; 4141.8Sthorpej } */ *uap = v; 4151.12Smycroft linux_sigset_t lss; 4161.12Smycroft sigset_t bss; 4171.12Smycroft 4181.12Smycroft lss = SCARG(uap, mask); 4191.12Smycroft linux_to_native_sigset(&lss, &bss); 4201.12Smycroft return (sigsuspend1(p, &bss)); 4211.3Sfvdl} 4221.3Sfvdl 4231.3Sfvdl/* 4241.3Sfvdl * The deprecated pause(2), which is really just an instance 4251.3Sfvdl * of sigsuspend(2). 4261.3Sfvdl */ 4271.3Sfvdlint 4281.9Smycroftlinux_sys_pause(p, v, retval) 4291.6Smycroft register struct proc *p; 4301.9Smycroft void *v; 4311.3Sfvdl register_t *retval; 4321.3Sfvdl{ 4331.3Sfvdl 4341.12Smycroft return (sigsuspend1(p, 0)); 4351.1Sfvdl} 4361.1Sfvdl 4371.1Sfvdl/* 4381.1Sfvdl * Once more: only a signal conversion is needed. 4391.1Sfvdl */ 4401.1Sfvdlint 4411.9Smycroftlinux_sys_kill(p, v, retval) 4421.6Smycroft register struct proc *p; 4431.8Sthorpej void *v; 4441.8Sthorpej register_t *retval; 4451.8Sthorpej{ 4461.9Smycroft struct linux_sys_kill_args /* { 4471.1Sfvdl syscallarg(int) pid; 4481.1Sfvdl syscallarg(int) signum; 4491.8Sthorpej } */ *uap = v; 4501.9Smycroft struct sys_kill_args ka; 4511.6Smycroft 4521.6Smycroft SCARG(&ka, pid) = SCARG(uap, pid); 4531.12Smycroft SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)]; 4541.9Smycroft return sys_kill(p, &ka, retval); 4551.1Sfvdl} 456