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)
65static struct sysctllog *compat_clog = NULL;
66#endif
67
68MODULE(MODULE_CLASS_EXEC, compat, NULL);
69
70int 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
76extern char sigcode[], esigcode[];
77struct uvm_object *emul_netbsd_object;
78#endif
79#endif
80#endif /* _MODULE */
81
82extern krwlock_t exec_lock;
83extern krwlock_t ttcompat_lock;
84
85static 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
222static int
223compat_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
318void
319compat_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
330void
331compat_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