1 /*- 2 * Copyright (c) 2015 Dmitry Chagin 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/signalvar.h> 33 34 #include <compat/linux/linux.h> 35 36 37 static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = { 38 LINUX_SIGHUP, /* SIGHUP */ 39 LINUX_SIGINT, /* SIGINT */ 40 LINUX_SIGQUIT, /* SIGQUIT */ 41 LINUX_SIGILL, /* SIGILL */ 42 LINUX_SIGTRAP, /* SIGTRAP */ 43 LINUX_SIGABRT, /* SIGABRT */ 44 0, /* SIGEMT */ 45 LINUX_SIGFPE, /* SIGFPE */ 46 LINUX_SIGKILL, /* SIGKILL */ 47 LINUX_SIGBUS, /* SIGBUS */ 48 LINUX_SIGSEGV, /* SIGSEGV */ 49 LINUX_SIGSYS, /* SIGSYS */ 50 LINUX_SIGPIPE, /* SIGPIPE */ 51 LINUX_SIGALRM, /* SIGALRM */ 52 LINUX_SIGTERM, /* SIGTERM */ 53 LINUX_SIGURG, /* SIGURG */ 54 LINUX_SIGSTOP, /* SIGSTOP */ 55 LINUX_SIGTSTP, /* SIGTSTP */ 56 LINUX_SIGCONT, /* SIGCONT */ 57 LINUX_SIGCHLD, /* SIGCHLD */ 58 LINUX_SIGTTIN, /* SIGTTIN */ 59 LINUX_SIGTTOU, /* SIGTTOU */ 60 LINUX_SIGIO, /* SIGIO */ 61 LINUX_SIGXCPU, /* SIGXCPU */ 62 LINUX_SIGXFSZ, /* SIGXFSZ */ 63 LINUX_SIGVTALRM,/* SIGVTALRM */ 64 LINUX_SIGPROF, /* SIGPROF */ 65 LINUX_SIGWINCH, /* SIGWINCH */ 66 0, /* SIGINFO */ 67 LINUX_SIGUSR1, /* SIGUSR1 */ 68 LINUX_SIGUSR2 /* SIGUSR2 */ 69 }; 70 71 static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = { 72 SIGHUP, /* LINUX_SIGHUP */ 73 SIGINT, /* LINUX_SIGINT */ 74 SIGQUIT, /* LINUX_SIGQUIT */ 75 SIGILL, /* LINUX_SIGILL */ 76 SIGTRAP, /* LINUX_SIGTRAP */ 77 SIGABRT, /* LINUX_SIGABRT */ 78 SIGBUS, /* LINUX_SIGBUS */ 79 SIGFPE, /* LINUX_SIGFPE */ 80 SIGKILL, /* LINUX_SIGKILL */ 81 SIGUSR1, /* LINUX_SIGUSR1 */ 82 SIGSEGV, /* LINUX_SIGSEGV */ 83 SIGUSR2, /* LINUX_SIGUSR2 */ 84 SIGPIPE, /* LINUX_SIGPIPE */ 85 SIGALRM, /* LINUX_SIGALRM */ 86 SIGTERM, /* LINUX_SIGTERM */ 87 SIGBUS, /* LINUX_SIGSTKFLT */ 88 SIGCHLD, /* LINUX_SIGCHLD */ 89 SIGCONT, /* LINUX_SIGCONT */ 90 SIGSTOP, /* LINUX_SIGSTOP */ 91 SIGTSTP, /* LINUX_SIGTSTP */ 92 SIGTTIN, /* LINUX_SIGTTIN */ 93 SIGTTOU, /* LINUX_SIGTTOU */ 94 SIGURG, /* LINUX_SIGURG */ 95 SIGXCPU, /* LINUX_SIGXCPU */ 96 SIGXFSZ, /* LINUX_SIGXFSZ */ 97 SIGVTALRM, /* LINUX_SIGVTALARM */ 98 SIGPROF, /* LINUX_SIGPROF */ 99 SIGWINCH, /* LINUX_SIGWINCH */ 100 SIGIO, /* LINUX_SIGIO */ 101 /* 102 * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal 103 * to the first unused FreeBSD signal number. Since Linux supports 104 * signals from 1 to 64 we are ok here as our SIGRTMIN = 65. 105 */ 106 SIGRTMIN, /* LINUX_SIGPWR */ 107 SIGSYS /* LINUX_SIGSYS */ 108 }; 109 110 /* 111 * Map Linux RT signals to the FreeBSD RT signals. 112 */ 113 static inline int 114 linux_to_bsd_rt_signal(int sig) 115 { 116 117 return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN); 118 } 119 120 static inline int 121 bsd_to_linux_rt_signal(int sig) 122 { 123 124 return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN); 125 } 126 127 int 128 linux_to_bsd_signal(int sig) 129 { 130 131 KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("invalid Linux signal %d\n", sig)); 132 133 if (sig < LINUX_SIGRTMIN) 134 return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]); 135 136 return (linux_to_bsd_rt_signal(sig)); 137 } 138 139 int 140 bsd_to_linux_signal(int sig) 141 { 142 143 if (sig <= LINUX_SIGTBLSZ) 144 return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]); 145 if (sig == SIGRTMIN) 146 return (LINUX_SIGPWR); 147 148 return (bsd_to_linux_rt_signal(sig)); 149 } 150 151 int 152 linux_to_bsd_sigaltstack(int lsa) 153 { 154 int bsa = 0; 155 156 if (lsa & LINUX_SS_DISABLE) 157 bsa |= SS_DISABLE; 158 /* 159 * Linux ignores SS_ONSTACK flag for ss 160 * parameter while FreeBSD prohibits it. 161 */ 162 return (bsa); 163 } 164 165 int 166 bsd_to_linux_sigaltstack(int bsa) 167 { 168 int lsa = 0; 169 170 if (bsa & SS_DISABLE) 171 lsa |= LINUX_SS_DISABLE; 172 if (bsa & SS_ONSTACK) 173 lsa |= LINUX_SS_ONSTACK; 174 return (lsa); 175 } 176 177 void 178 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 179 { 180 int b, l; 181 182 SIGEMPTYSET(*bss); 183 for (l = 1; l <= LINUX_SIGRTMAX; l++) { 184 if (LINUX_SIGISMEMBER(*lss, l)) { 185 b = linux_to_bsd_signal(l); 186 if (b) 187 SIGADDSET(*bss, b); 188 } 189 } 190 } 191 192 void 193 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 194 { 195 int b, l; 196 197 LINUX_SIGEMPTYSET(*lss); 198 for (b = 1; b <= SIGRTMAX; b++) { 199 if (SIGISMEMBER(*bss, b)) { 200 l = bsd_to_linux_signal(b); 201 if (l) 202 LINUX_SIGADDSET(*lss, l); 203 } 204 } 205 } 206