1 | /* $NetBSD: compat_mod.c,v 1.24 2016/11/05 23:30:22 pgoyette Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * This code is derived from software developed for The NetBSD Foundation |
8 | * by Andrew Doran. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | /* |
33 | * Linkage for the compat module: spaghetti. |
34 | */ |
35 | |
36 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: compat_mod.c,v 1.24 2016/11/05 23:30:22 pgoyette Exp $" ); |
38 | |
39 | #ifdef _KERNEL_OPT |
40 | #include "opt_compat_netbsd.h" |
41 | #include "opt_compat_43.h" |
42 | #include "opt_ntp.h" |
43 | #include "opt_sysv.h" |
44 | #include "opt_lfs.h" |
45 | #endif |
46 | |
47 | #include <sys/systm.h> |
48 | #include <sys/module.h> |
49 | #include <sys/rwlock.h> |
50 | #include <sys/tty.h> |
51 | #include <sys/signalvar.h> |
52 | #include <sys/syscall.h> |
53 | #include <sys/syscallargs.h> |
54 | #include <sys/syscallvar.h> |
55 | #include <sys/sysctl.h> |
56 | |
57 | #include <uvm/uvm_extern.h> |
58 | #include <uvm/uvm_object.h> |
59 | |
60 | #include <compat/common/compat_util.h> |
61 | #include <compat/common/compat_mod.h> |
62 | #include <compat/common/if_43.h> |
63 | |
64 | #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50) |
65 | static struct sysctllog *compat_clog = NULL; |
66 | #endif |
67 | |
68 | MODULE(MODULE_CLASS_EXEC, compat, NULL); |
69 | |
70 | int ttcompat(struct tty *, u_long, void *, int, struct lwp *); |
71 | |
72 | #ifdef _MODULE |
73 | #ifdef COMPAT_16 |
74 | #if !defined(__amd64__) || defined(COMPAT_NETBSD32) |
75 | #define COMPAT_SIGCONTEXT |
76 | extern char sigcode[], esigcode[]; |
77 | struct uvm_object *emul_netbsd_object; |
78 | #endif |
79 | #endif |
80 | #endif /* _MODULE */ |
81 | |
82 | extern krwlock_t exec_lock; |
83 | extern krwlock_t ttcompat_lock; |
84 | |
85 | static const struct syscall_package compat_syscalls[] = { |
86 | #if defined(COMPAT_43) |
87 | { SYS_compat_43_fstat43, 0, (sy_call_t *)compat_43_sys_fstat }, |
88 | { SYS_compat_43_lstat43, 0, (sy_call_t *)compat_43_sys_lstat }, |
89 | { SYS_compat_43_oaccept, 0, (sy_call_t *)compat_43_sys_accept }, |
90 | { SYS_compat_43_ocreat, 0, (sy_call_t *)compat_43_sys_creat }, |
91 | { SYS_compat_43_oftruncate, 0, (sy_call_t *)compat_43_sys_ftruncate }, |
92 | { SYS_compat_43_ogetdirentries, 0, (sy_call_t *)compat_43_sys_getdirentries }, |
93 | { SYS_compat_43_ogetdtablesize, 0, (sy_call_t *)compat_43_sys_getdtablesize }, |
94 | { SYS_compat_43_ogethostid, 0, (sy_call_t *)compat_43_sys_gethostid }, |
95 | { SYS_compat_43_ogethostname, 0, (sy_call_t *)compat_43_sys_gethostname }, |
96 | { SYS_compat_43_ogetkerninfo, 0, (sy_call_t *)compat_43_sys_getkerninfo }, |
97 | { SYS_compat_43_ogetpagesize, 0, (sy_call_t *)compat_43_sys_getpagesize }, |
98 | { SYS_compat_43_ogetpeername, 0, (sy_call_t *)compat_43_sys_getpeername }, |
99 | { SYS_compat_43_ogetrlimit, 0, (sy_call_t *)compat_43_sys_getrlimit }, |
100 | { SYS_compat_43_ogetsockname, 0, (sy_call_t *)compat_43_sys_getsockname }, |
101 | { SYS_compat_43_okillpg, 0, (sy_call_t *)compat_43_sys_killpg }, |
102 | { SYS_compat_43_olseek, 0, (sy_call_t *)compat_43_sys_lseek }, |
103 | { SYS_compat_43_ommap, 0, (sy_call_t *)compat_43_sys_mmap }, |
104 | { SYS_compat_43_oquota, 0, (sy_call_t *)compat_43_sys_quota }, |
105 | { SYS_compat_43_orecv, 0, (sy_call_t *)compat_43_sys_recv }, |
106 | { SYS_compat_43_orecvfrom, 0, (sy_call_t *)compat_43_sys_recvfrom }, |
107 | { SYS_compat_43_orecvmsg, 0, (sy_call_t *)compat_43_sys_recvmsg }, |
108 | { SYS_compat_43_osend, 0, (sy_call_t *)compat_43_sys_send }, |
109 | { SYS_compat_43_osendmsg, 0, (sy_call_t *)compat_43_sys_sendmsg }, |
110 | { SYS_compat_43_osethostid, 0, (sy_call_t *)compat_43_sys_sethostid }, |
111 | { SYS_compat_43_osethostname, 0, (sy_call_t *)compat_43_sys_sethostname }, |
112 | { SYS_compat_43_osetrlimit, 0, (sy_call_t *)compat_43_sys_setrlimit }, |
113 | { SYS_compat_43_osigblock, 0, (sy_call_t *)compat_43_sys_sigblock }, |
114 | { SYS_compat_43_osigsetmask, 0, (sy_call_t *)compat_43_sys_sigsetmask }, |
115 | { SYS_compat_43_osigstack, 0, (sy_call_t *)compat_43_sys_sigstack }, |
116 | { SYS_compat_43_osigvec, 0, (sy_call_t *)compat_43_sys_sigvec }, |
117 | { SYS_compat_43_otruncate, 0, (sy_call_t *)compat_43_sys_truncate }, |
118 | { SYS_compat_43_owait, 0, (sy_call_t *)compat_43_sys_wait }, |
119 | { SYS_compat_43_stat43, 0, (sy_call_t *)compat_43_sys_stat }, |
120 | #endif |
121 | |
122 | #if defined(COMPAT_09) |
123 | { SYS_compat_09_ogetdomainname, 0, (sy_call_t *)compat_09_sys_getdomainname }, |
124 | { SYS_compat_09_osetdomainname, 0, (sy_call_t *)compat_09_sys_setdomainname }, |
125 | { SYS_compat_09_ouname, 0, (sy_call_t *)compat_09_sys_uname }, |
126 | #endif |
127 | |
128 | #if defined(COMPAT_12) |
129 | { SYS_compat_12_fstat12, 0, (sy_call_t *)compat_12_sys_fstat }, |
130 | { SYS_compat_12_getdirentries, 0, (sy_call_t *)compat_12_sys_getdirentries }, |
131 | { SYS_compat_12_lstat12, 0, (sy_call_t *)compat_12_sys_lstat }, |
132 | { SYS_compat_12_msync, 0, (sy_call_t *)compat_12_sys_msync }, |
133 | { SYS_compat_12_oreboot, 0, (sy_call_t *)compat_12_sys_reboot }, |
134 | { SYS_compat_12_oswapon, 0, (sy_call_t *)compat_12_sys_swapon }, |
135 | { SYS_compat_12_stat12, 0, (sy_call_t *)compat_12_sys_stat }, |
136 | #endif |
137 | |
138 | #if defined(COMPAT_13) |
139 | { SYS_compat_13_sigaction13, 0, (sy_call_t *)compat_13_sys_sigaction }, |
140 | { SYS_compat_13_sigaltstack13, 0, (sy_call_t *)compat_13_sys_sigaltstack }, |
141 | { SYS_compat_13_sigpending13, 0, (sy_call_t *)compat_13_sys_sigpending }, |
142 | { SYS_compat_13_sigprocmask13, 0, (sy_call_t *)compat_13_sys_sigprocmask }, |
143 | { SYS_compat_13_sigreturn13, 0, (sy_call_t *)compat_13_sys_sigreturn }, |
144 | { SYS_compat_13_sigsuspend13, 0, (sy_call_t *)compat_13_sys_sigsuspend }, |
145 | #endif |
146 | |
147 | #if defined(COMPAT_16) |
148 | #if defined(COMPAT_SIGCONTEXT) |
149 | { SYS_compat_16___sigaction14, 0, (sy_call_t *)compat_16_sys___sigaction14 }, |
150 | { SYS_compat_16___sigreturn14, 0, (sy_call_t *)compat_16_sys___sigreturn14 }, |
151 | #endif |
152 | #endif |
153 | |
154 | #if defined(COMPAT_20) |
155 | { SYS_compat_20_fhstatfs, 0, (sy_call_t *)compat_20_sys_fhstatfs }, |
156 | { SYS_compat_20_fstatfs, 0, (sy_call_t *)compat_20_sys_fstatfs }, |
157 | { SYS_compat_20_getfsstat, 0, (sy_call_t *)compat_20_sys_getfsstat }, |
158 | { SYS_compat_20_statfs, 0, (sy_call_t *)compat_20_sys_statfs }, |
159 | #endif |
160 | |
161 | #if defined(COMPAT_30) |
162 | { SYS_compat_30___fhstat30, 0, (sy_call_t *)compat_30_sys___fhstat30 }, |
163 | { SYS_compat_30___fstat13, 0, (sy_call_t *)compat_30_sys___fstat13 }, |
164 | { SYS_compat_30___lstat13, 0, (sy_call_t *)compat_30_sys___lstat13 }, |
165 | { SYS_compat_30___stat13, 0, (sy_call_t *)compat_30_sys___stat13 }, |
166 | { SYS_compat_30_fhopen, 0, (sy_call_t *)compat_30_sys_fhopen }, |
167 | { SYS_compat_30_fhstat, 0, (sy_call_t *)compat_30_sys_fhstat }, |
168 | { SYS_compat_30_fhstatvfs1, 0, (sy_call_t *)compat_30_sys_fhstatvfs1 }, |
169 | { SYS_compat_30_getdents, 0, (sy_call_t *)compat_30_sys_getdents }, |
170 | { SYS_compat_30_getfh, 0, (sy_call_t *)compat_30_sys_getfh }, |
171 | { SYS_compat_30_socket, 0, (sy_call_t *)compat_30_sys_socket }, |
172 | #endif |
173 | |
174 | #if defined(COMPAT_40) |
175 | { SYS_compat_40_mount, 0, (sy_call_t *)compat_40_sys_mount }, |
176 | #endif |
177 | #if defined(COMPAT_50) |
178 | { SYS_compat_50_wait4, 0, (sy_call_t *)compat_50_sys_wait4 }, |
179 | { SYS_compat_50_mknod, 0, (sy_call_t *)compat_50_sys_mknod }, |
180 | { SYS_compat_50_setitimer, 0, (sy_call_t *)compat_50_sys_setitimer }, |
181 | { SYS_compat_50_getitimer, 0, (sy_call_t *)compat_50_sys_getitimer }, |
182 | { SYS_compat_50_select, 0, (sy_call_t *)compat_50_sys_select }, |
183 | { SYS_compat_50_gettimeofday, 0, (sy_call_t *)compat_50_sys_gettimeofday }, |
184 | { SYS_compat_50_getrusage, 0, (sy_call_t *)compat_50_sys_getrusage }, |
185 | { SYS_compat_50_settimeofday, 0, (sy_call_t *)compat_50_sys_settimeofday }, |
186 | { SYS_compat_50_utimes, 0, (sy_call_t *)compat_50_sys_utimes }, |
187 | { SYS_compat_50_adjtime, 0, (sy_call_t *)compat_50_sys_adjtime }, |
188 | #ifdef LFS |
189 | { SYS_compat_50_lfs_segwait, 0, (sy_call_t *)compat_50_sys_lfs_segwait }, |
190 | #endif |
191 | { SYS_compat_50_futimes, 0, (sy_call_t *)compat_50_sys_futimes }, |
192 | { SYS_compat_50_clock_gettime, 0, (sy_call_t *)compat_50_sys_clock_gettime }, |
193 | { SYS_compat_50_clock_settime, 0, (sy_call_t *)compat_50_sys_clock_settime }, |
194 | { SYS_compat_50_clock_getres, 0, (sy_call_t *)compat_50_sys_clock_getres }, |
195 | { SYS_compat_50_timer_settime, 0, (sy_call_t *)compat_50_sys_timer_settime }, |
196 | { SYS_compat_50_timer_gettime, 0, (sy_call_t *)compat_50_sys_timer_gettime }, |
197 | { SYS_compat_50_nanosleep, 0, (sy_call_t *)compat_50_sys_nanosleep }, |
198 | { SYS_compat_50___sigtimedwait, 0, (sy_call_t *)compat_50_sys___sigtimedwait }, |
199 | { SYS_compat_50_mq_timedsend, 0, (sy_call_t *)compat_50_sys_mq_timedsend }, |
200 | { SYS_compat_50_mq_timedreceive, 0, (sy_call_t *)compat_50_sys_mq_timedreceive }, |
201 | { SYS_compat_50_lutimes, 0, (sy_call_t *)compat_50_sys_lutimes }, |
202 | { SYS_compat_50__lwp_park, 0, (sy_call_t *)compat_50_sys__lwp_park }, |
203 | { SYS_compat_50_kevent, 0, (sy_call_t *)compat_50_sys_kevent }, |
204 | { SYS_compat_50_pselect, 0, (sy_call_t *)compat_50_sys_pselect }, |
205 | { SYS_compat_50_pollts, 0, (sy_call_t *)compat_50_sys_pollts }, |
206 | { SYS_compat_50___stat30, 0, (sy_call_t *)compat_50_sys___stat30 }, |
207 | { SYS_compat_50___fstat30, 0, (sy_call_t *)compat_50_sys___fstat30 }, |
208 | { SYS_compat_50___lstat30, 0, (sy_call_t *)compat_50_sys___lstat30 }, |
209 | # if defined(NTP) |
210 | { SYS_compat_50___ntp_gettime30, 0, (sy_call_t *)compat_50_sys___ntp_gettime30 }, |
211 | # endif |
212 | { SYS_compat_50___fhstat40, 0, (sy_call_t *)compat_50_sys___fhstat40 }, |
213 | { SYS_compat_50_aio_suspend, 0, (sy_call_t *)compat_50_sys_aio_suspend }, |
214 | { SYS_compat_50_quotactl, 0, (sy_call_t *)compat_50_sys_quotactl }, |
215 | #endif |
216 | #if defined(COMPAT_60) |
217 | { SYS_compat_60__lwp_park, 0, (sy_call_t *)compat_60_sys__lwp_park }, |
218 | #endif |
219 | { 0, 0, NULL }, |
220 | }; |
221 | |
222 | static int |
223 | compat_modcmd(modcmd_t cmd, void *arg) |
224 | { |
225 | #ifdef COMPAT_16 |
226 | proc_t *p; |
227 | #endif |
228 | int error; |
229 | |
230 | switch (cmd) { |
231 | case MODULE_CMD_INIT: |
232 | error = syscall_establish(NULL, compat_syscalls); |
233 | if (error != 0) { |
234 | return error; |
235 | } |
236 | #ifdef COMPAT_43 |
237 | KASSERT(ttcompatvec == NULL); |
238 | ttcompatvec = ttcompat; |
239 | if_43_init(); |
240 | #endif |
241 | #ifdef COMPAT_16 |
242 | #if defined(COMPAT_SIGCONTEXT) |
243 | KASSERT(emul_netbsd.e_sigobject == NULL); |
244 | rw_enter(&exec_lock, RW_WRITER); |
245 | emul_netbsd.e_sigcode = sigcode; |
246 | emul_netbsd.e_esigcode = esigcode; |
247 | emul_netbsd.e_sigobject = &emul_netbsd_object; |
248 | rw_exit(&exec_lock); |
249 | KASSERT(sendsig_sigcontext_vec == NULL); |
250 | sendsig_sigcontext_vec = sendsig_sigcontext; |
251 | #endif |
252 | #endif |
253 | compat_sysctl_init(); |
254 | return 0; |
255 | |
256 | case MODULE_CMD_FINI: |
257 | #ifdef COMPAT_16 |
258 | /* |
259 | * Ensure sendsig_sigcontext() is not being used. |
260 | * module_lock prevents the flag being set on any |
261 | * further processes while we are here. See |
262 | * sigaction1() for the opposing half. |
263 | */ |
264 | mutex_enter(proc_lock); |
265 | PROCLIST_FOREACH(p, &allproc) { |
266 | if ((p->p_lflag & PL_SIGCOMPAT) != 0) { |
267 | break; |
268 | } |
269 | } |
270 | mutex_exit(proc_lock); |
271 | if (p != NULL) { |
272 | return EBUSY; |
273 | } |
274 | sendsig_sigcontext_vec = NULL; |
275 | #endif |
276 | /* Unlink the system calls. */ |
277 | error = syscall_disestablish(NULL, compat_syscalls); |
278 | if (error != 0) { |
279 | return error; |
280 | } |
281 | #ifdef COMPAT_43 |
282 | /* Unlink ttcompatvec. */ |
283 | if (rw_tryenter(&ttcompat_lock, RW_WRITER)) { |
284 | ttcompatvec = NULL; |
285 | rw_exit(&ttcompat_lock); |
286 | } else { |
287 | error = syscall_establish(NULL, compat_syscalls); |
288 | KASSERT(error == 0); |
289 | return EBUSY; |
290 | } |
291 | #endif |
292 | #ifdef COMPAT_16 |
293 | #if defined(COMPAT_SIGCONTEXT) |
294 | /* |
295 | * The sigobject may persist if still in use, but |
296 | * is reference counted so will die eventually. |
297 | */ |
298 | rw_enter(&exec_lock, RW_WRITER); |
299 | if (emul_netbsd_object != NULL) { |
300 | (*emul_netbsd_object->pgops->pgo_detach) |
301 | (emul_netbsd_object); |
302 | } |
303 | emul_netbsd_object = NULL; |
304 | emul_netbsd.e_sigcode = NULL; |
305 | emul_netbsd.e_esigcode = NULL; |
306 | emul_netbsd.e_sigobject = NULL; |
307 | rw_exit(&exec_lock); |
308 | #endif |
309 | #endif /* COMPAT_16 */ |
310 | compat_sysctl_fini(); |
311 | return 0; |
312 | |
313 | default: |
314 | return ENOTTY; |
315 | } |
316 | } |
317 | |
318 | void |
319 | compat_sysctl_init(void) |
320 | { |
321 | |
322 | #if defined(COMPAT_09) || defined(COMPAT_43) |
323 | compat_sysctl_vfs(&compat_clog); |
324 | #endif |
325 | #if defined(COMPAT_50) |
326 | compat_sysctl_time(&compat_clog); |
327 | #endif |
328 | } |
329 | |
330 | void |
331 | compat_sysctl_fini(void) |
332 | { |
333 | |
334 | #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50) |
335 | sysctl_teardown(&compat_clog); |
336 | #endif |
337 | #if defined(COMPAT_43) |
338 | if_43_fini(); |
339 | #endif |
340 | } |
341 | |