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