1/*	$NetBSD: compat_mod.c,v 1.14 2011/08/08 23:44:06 jakllsch 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.14 2011/08/08 23:44:06 jakllsch 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
63#if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50)
64static struct sysctllog *compat_clog = NULL;
65#endif
66
67MODULE(MODULE_CLASS_MISC, compat, NULL);
68
69int	ttcompat(struct tty *, u_long, void *, int, struct lwp *);
70
71#ifdef COMPAT_16
72#if !(defined(__amd64__) && !defined(COMPAT_NETBSD32))
73extern char sigcode[], esigcode[];
74struct uvm_object *emul_netbsd_object;
75#endif
76#endif
77
78extern krwlock_t exec_lock;
79extern krwlock_t ttcompat_lock;
80
81static const struct syscall_package compat_syscalls[] = {
82#if defined(COMPAT_43)
83	{ SYS_compat_43_fstat43, 0, (sy_call_t *)compat_43_sys_fstat },
84	{ SYS_compat_43_lstat43, 0, (sy_call_t *)compat_43_sys_lstat },
85	{ SYS_compat_43_oaccept, 0, (sy_call_t *)compat_43_sys_accept },
86	{ SYS_compat_43_ocreat, 0, (sy_call_t *)compat_43_sys_creat },
87	{ SYS_compat_43_oftruncate, 0, (sy_call_t *)compat_43_sys_ftruncate },
88	{ SYS_compat_43_ogetdirentries, 0, (sy_call_t *)compat_43_sys_getdirentries },
89	{ SYS_compat_43_ogetdtablesize, 0, (sy_call_t *)compat_43_sys_getdtablesize },
90	{ SYS_compat_43_ogethostid, 0, (sy_call_t *)compat_43_sys_gethostid },
91	{ SYS_compat_43_ogethostname, 0, (sy_call_t *)compat_43_sys_gethostname },
92	{ SYS_compat_43_ogetkerninfo, 0, (sy_call_t *)compat_43_sys_getkerninfo },
93	{ SYS_compat_43_ogetpagesize, 0, (sy_call_t *)compat_43_sys_getpagesize },
94	{ SYS_compat_43_ogetpeername, 0, (sy_call_t *)compat_43_sys_getpeername },
95	{ SYS_compat_43_ogetrlimit, 0, (sy_call_t *)compat_43_sys_getrlimit },
96	{ SYS_compat_43_ogetsockname, 0, (sy_call_t *)compat_43_sys_getsockname },
97	{ SYS_compat_43_okillpg, 0, (sy_call_t *)compat_43_sys_killpg },
98	{ SYS_compat_43_olseek, 0, (sy_call_t *)compat_43_sys_lseek },
99	{ SYS_compat_43_ommap, 0, (sy_call_t *)compat_43_sys_mmap },
100	{ SYS_compat_43_oquota, 0, (sy_call_t *)compat_43_sys_quota },
101	{ SYS_compat_43_orecv, 0, (sy_call_t *)compat_43_sys_recv },
102	{ SYS_compat_43_orecvfrom, 0, (sy_call_t *)compat_43_sys_recvfrom },
103	{ SYS_compat_43_orecvmsg, 0, (sy_call_t *)compat_43_sys_recvmsg },
104	{ SYS_compat_43_osend, 0, (sy_call_t *)compat_43_sys_send },
105	{ SYS_compat_43_osendmsg, 0, (sy_call_t *)compat_43_sys_sendmsg },
106	{ SYS_compat_43_osethostid, 0, (sy_call_t *)compat_43_sys_sethostid },
107	{ SYS_compat_43_osethostname, 0, (sy_call_t *)compat_43_sys_sethostname },
108	{ SYS_compat_43_osetrlimit, 0, (sy_call_t *)compat_43_sys_setrlimit },
109	{ SYS_compat_43_osigblock, 0, (sy_call_t *)compat_43_sys_sigblock },
110	{ SYS_compat_43_osigsetmask, 0, (sy_call_t *)compat_43_sys_sigsetmask },
111	{ SYS_compat_43_osigstack, 0, (sy_call_t *)compat_43_sys_sigstack },
112	{ SYS_compat_43_osigvec, 0, (sy_call_t *)compat_43_sys_sigvec },
113	{ SYS_compat_43_otruncate, 0, (sy_call_t *)compat_43_sys_truncate },
114	{ SYS_compat_43_owait, 0, (sy_call_t *)compat_43_sys_wait },
115	{ SYS_compat_43_stat43, 0, (sy_call_t *)compat_43_sys_stat },
116#endif
117
118#if defined(COMPAT_09)
119	{ SYS_compat_09_ogetdomainname, 0, (sy_call_t *)compat_09_sys_getdomainname },
120	{ SYS_compat_09_osetdomainname, 0, (sy_call_t *)compat_09_sys_setdomainname },
121	{ SYS_compat_09_ouname, 0, (sy_call_t *)compat_09_sys_uname },
122#endif
123
124#if defined(COMPAT_10) && !defined(_LP64)
125# if defined(SYSVMSG)
126	{ SYS_compat_10_omsgsys, 0, (sy_call_t *)compat_10_sys_msgsys },
127# endif
128# if defined(SYSVSEM)
129	{ SYS_compat_10_osemsys, 0, (sy_call_t *)compat_10_sys_semsys },
130# endif
131# if defined(SYSVSHM)
132	{ SYS_compat_10_oshmsys, 0, (sy_call_t *)compat_10_sys_shmsys },
133# endif
134#endif	/* defined(COMPAT_10) && !defined(_LP64) */
135
136#if defined(COMPAT_12)
137	{ SYS_compat_12_fstat12, 0, (sy_call_t *)compat_12_sys_fstat },
138	{ SYS_compat_12_getdirentries, 0, (sy_call_t *)compat_12_sys_getdirentries },
139	{ SYS_compat_12_lstat12, 0, (sy_call_t *)compat_12_sys_lstat },
140	{ SYS_compat_12_msync, 0, (sy_call_t *)compat_12_sys_msync },
141	{ SYS_compat_12_oreboot, 0, (sy_call_t *)compat_12_sys_reboot },
142	{ SYS_compat_12_oswapon, 0, (sy_call_t *)compat_12_sys_swapon },
143	{ SYS_compat_12_stat12, 0, (sy_call_t *)compat_12_sys_stat },
144#endif
145
146#if defined(COMPAT_13)
147	{ SYS_compat_13_sigaction13, 0, (sy_call_t *)compat_13_sys_sigaction },
148	{ SYS_compat_13_sigaltstack13, 0, (sy_call_t *)compat_13_sys_sigaltstack },
149	{ SYS_compat_13_sigpending13, 0, (sy_call_t *)compat_13_sys_sigpending },
150	{ SYS_compat_13_sigprocmask13, 0, (sy_call_t *)compat_13_sys_sigprocmask },
151	{ SYS_compat_13_sigreturn13, 0, (sy_call_t *)compat_13_sys_sigreturn },
152	{ SYS_compat_13_sigsuspend13, 0, (sy_call_t *)compat_13_sys_sigsuspend },
153#endif
154
155#if defined(COMPAT_14)
156# if defined(SYSVSEM)
157	{ SYS_compat_14___semctl, 0, (sy_call_t *)compat_14_sys___semctl },
158# endif
159# if defined(SYSVMSG)
160	{ SYS_compat_14_msgctl, 0, (sy_call_t *)compat_14_sys_msgctl },
161# endif
162# if defined(SYSVSHM)
163	{ SYS_compat_14_shmctl, 0, (sy_call_t *)compat_14_sys_shmctl },
164# endif
165#endif
166
167#if defined(COMPAT_16)
168#if !(defined(__amd64__) && !defined(COMPAT_NETBSD32))
169	{ SYS_compat_16___sigaction14, 0, (sy_call_t *)compat_16_sys___sigaction14 },
170	{ SYS_compat_16___sigreturn14, 0, (sy_call_t *)compat_16_sys___sigreturn14 },
171#endif
172#endif
173
174#if defined(COMPAT_20)
175	{ SYS_compat_20_fhstatfs, 0, (sy_call_t *)compat_20_sys_fhstatfs },
176	{ SYS_compat_20_fstatfs, 0, (sy_call_t *)compat_20_sys_fstatfs },
177	{ SYS_compat_20_getfsstat, 0, (sy_call_t *)compat_20_sys_getfsstat },
178	{ SYS_compat_20_statfs, 0, (sy_call_t *)compat_20_sys_statfs },
179#endif
180
181#if defined(COMPAT_30)
182	{ SYS_compat_30___fhstat30, 0, (sy_call_t *)compat_30_sys___fhstat30 },
183	{ SYS_compat_30___fstat13, 0, (sy_call_t *)compat_30_sys___fstat13 },
184	{ SYS_compat_30___lstat13, 0, (sy_call_t *)compat_30_sys___lstat13 },
185	{ SYS_compat_30___stat13, 0, (sy_call_t *)compat_30_sys___stat13 },
186	{ SYS_compat_30_fhopen, 0, (sy_call_t *)compat_30_sys_fhopen },
187	{ SYS_compat_30_fhstat, 0, (sy_call_t *)compat_30_sys_fhstat },
188	{ SYS_compat_30_fhstatvfs1, 0, (sy_call_t *)compat_30_sys_fhstatvfs1 },
189	{ SYS_compat_30_getdents, 0, (sy_call_t *)compat_30_sys_getdents },
190	{ SYS_compat_30_getfh, 0, (sy_call_t *)compat_30_sys_getfh },
191	{ SYS_compat_30_socket, 0, (sy_call_t *)compat_30_sys_socket },
192#endif
193
194#if defined(COMPAT_40)
195	{ SYS_compat_40_mount, 0, (sy_call_t *)compat_40_sys_mount },
196#endif
197#if defined(COMPAT_50)
198	{ SYS_compat_50_wait4, 0, (sy_call_t *)compat_50_sys_wait4 },
199	{ SYS_compat_50_mknod, 0, (sy_call_t *)compat_50_sys_mknod },
200	{ SYS_compat_50_setitimer, 0, (sy_call_t *)compat_50_sys_setitimer },
201	{ SYS_compat_50_getitimer, 0, (sy_call_t *)compat_50_sys_getitimer },
202	{ SYS_compat_50_select, 0, (sy_call_t *)compat_50_sys_select },
203	{ SYS_compat_50_gettimeofday, 0, (sy_call_t *)compat_50_sys_gettimeofday },
204	{ SYS_compat_50_getrusage, 0, (sy_call_t *)compat_50_sys_getrusage },
205	{ SYS_compat_50_settimeofday, 0, (sy_call_t *)compat_50_sys_settimeofday },
206	{ SYS_compat_50_utimes, 0, (sy_call_t *)compat_50_sys_utimes },
207	{ SYS_compat_50_adjtime, 0, (sy_call_t *)compat_50_sys_adjtime },
208#ifdef LFS
209	{ SYS_compat_50_lfs_segwait, 0, (sy_call_t *)compat_50_sys_lfs_segwait },
210#endif
211	{ SYS_compat_50_futimes, 0, (sy_call_t *)compat_50_sys_futimes },
212	{ SYS_compat_50_clock_gettime, 0, (sy_call_t *)compat_50_sys_clock_gettime },
213	{ SYS_compat_50_clock_settime, 0, (sy_call_t *)compat_50_sys_clock_settime },
214	{ SYS_compat_50_clock_getres, 0, (sy_call_t *)compat_50_sys_clock_getres },
215	{ SYS_compat_50_timer_settime, 0, (sy_call_t *)compat_50_sys_timer_settime },
216	{ SYS_compat_50_timer_gettime, 0, (sy_call_t *)compat_50_sys_timer_gettime },
217	{ SYS_compat_50_nanosleep, 0, (sy_call_t *)compat_50_sys_nanosleep },
218	{ SYS_compat_50___sigtimedwait, 0, (sy_call_t *)compat_50_sys___sigtimedwait },
219	{ SYS_compat_50_mq_timedsend, 0, (sy_call_t *)compat_50_sys_mq_timedsend },
220	{ SYS_compat_50_mq_timedreceive, 0, (sy_call_t *)compat_50_sys_mq_timedreceive },
221	{ SYS_compat_50_lutimes, 0, (sy_call_t *)compat_50_sys_lutimes },
222# if defined(SYSVSEM)
223	{ SYS_compat_50_____semctl13, 0, (sy_call_t *)compat_50_sys_____semctl13 },
224# endif
225# if defined(SYSVMSG)
226	{ SYS_compat_50___msgctl13, 0, (sy_call_t *)compat_50_sys___msgctl13 },
227# endif
228# if defined(SYSVSHM)
229	{ SYS_compat_50___shmctl13, 0, (sy_call_t *)compat_50_sys___shmctl13 },
230# endif
231	{ SYS_compat_50__lwp_park, 0, (sy_call_t *)compat_50_sys__lwp_park },
232	{ SYS_compat_50_kevent, 0, (sy_call_t *)compat_50_sys_kevent },
233	{ SYS_compat_50_pselect, 0, (sy_call_t *)compat_50_sys_pselect },
234	{ SYS_compat_50_pollts, 0, (sy_call_t *)compat_50_sys_pollts },
235	{ SYS_compat_50___stat30, 0, (sy_call_t *)compat_50_sys___stat30 },
236	{ SYS_compat_50___fstat30, 0, (sy_call_t *)compat_50_sys___fstat30 },
237	{ SYS_compat_50___lstat30, 0, (sy_call_t *)compat_50_sys___lstat30 },
238# if defined(NTP)
239	{ SYS_compat_50___ntp_gettime30, 0, (sy_call_t *)compat_50_sys___ntp_gettime30 },
240# endif
241	{ SYS_compat_50___fhstat40, 0, (sy_call_t *)compat_50_sys___fhstat40 },
242	{ SYS_compat_50_aio_suspend, 0, (sy_call_t *)compat_50_sys_aio_suspend },
243	{ SYS_compat_50_quotactl, 0, (sy_call_t *)compat_50_sys_quotactl },
244#endif
245	{ 0, 0, NULL },
246};
247
248static int
249compat_modcmd(modcmd_t cmd, void *arg)
250{
251#ifdef COMPAT_16
252	proc_t *p;
253#endif
254	int error;
255
256	switch (cmd) {
257	case MODULE_CMD_INIT:
258		error = syscall_establish(NULL, compat_syscalls);
259		if (error != 0) {
260			return error;
261		}
262#ifdef COMPAT_43
263		KASSERT(ttcompatvec == NULL);
264		ttcompatvec = ttcompat;
265#endif
266#ifdef COMPAT_16
267#if !(defined(__amd64__) && !defined(COMPAT_NETBSD32))
268		KASSERT(emul_netbsd.e_sigobject == NULL);
269		rw_enter(&exec_lock, RW_WRITER);
270		emul_netbsd.e_sigcode = sigcode;
271		emul_netbsd.e_esigcode = esigcode;
272		emul_netbsd.e_sigobject = &emul_netbsd_object;
273		rw_exit(&exec_lock);
274		KASSERT(sendsig_sigcontext_vec == NULL);
275		sendsig_sigcontext_vec = sendsig_sigcontext;
276#endif
277#endif
278		compat_sysctl_init();
279		return 0;
280
281	case MODULE_CMD_FINI:
282#ifdef COMPAT_16
283		/*
284		 * Ensure sendsig_sigcontext() is not being used.
285		 * module_lock prevents the flag being set on any
286		 * further processes while we are here.  See
287		 * sigaction1() for the opposing half.
288		 */
289		mutex_enter(proc_lock);
290		PROCLIST_FOREACH(p, &allproc) {
291			if ((p->p_lflag & PL_SIGCOMPAT) != 0) {
292				break;
293			}
294		}
295		mutex_exit(proc_lock);
296		if (p != NULL) {
297			return EBUSY;
298		}
299		sendsig_sigcontext_vec = NULL;
300#endif
301		/* Unlink the system calls. */
302		error = syscall_disestablish(NULL, compat_syscalls);
303		if (error != 0) {
304			return error;
305		}
306#ifdef COMPAT_43
307		/* Unlink ttcompatvec. */
308		if (rw_tryenter(&ttcompat_lock, RW_WRITER)) {
309			ttcompatvec = NULL;
310			rw_exit(&ttcompat_lock);
311		} else {
312			error = syscall_establish(NULL, compat_syscalls);
313			KASSERT(error == 0);
314			return EBUSY;
315		}
316#endif
317#ifdef COMPAT_16
318#if !(defined(__amd64__) && !defined(COMPAT_NETBSD32))
319		/*
320		 * The sigobject may persist if still in use, but
321		 * is reference counted so will die eventually.
322		 */
323		rw_enter(&exec_lock, RW_WRITER);
324		if (emul_netbsd_object != NULL) {
325			(*emul_netbsd_object->pgops->pgo_detach)
326			    (emul_netbsd_object);
327		}
328		emul_netbsd_object = NULL;
329		emul_netbsd.e_sigcode = NULL;
330		emul_netbsd.e_esigcode = NULL;
331		emul_netbsd.e_sigobject = NULL;
332		rw_exit(&exec_lock);
333#endif
334#endif	/* COMPAT_16 */
335		compat_sysctl_fini();
336		return 0;
337
338	default:
339		return ENOTTY;
340	}
341}
342
343void
344compat_sysctl_init(void)
345{
346
347#if defined(COMPAT_09) || defined(COMPAT_43)
348	compat_sysctl_vfs(&compat_clog);
349#endif
350#if defined(COMPAT_50)
351	compat_sysctl_time(&compat_clog);
352#endif
353}
354
355void
356compat_sysctl_fini(void)
357{
358
359#if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50)
360        sysctl_teardown(&compat_clog);
361#endif
362}
363