xref: /freebsd/sys/compat/linux/linux.c (revision 63a938566d524836885917d95bd491aa4400b181)
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