367 lines
13 KiB
C
367 lines
13 KiB
C
/* $NetBSD: compat_mod.c,v 1.19 2013/03/29 01:02:49 christos Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software developed for The NetBSD Foundation
|
|
* by Andrew Doran.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* Linkage for the compat module: spaghetti.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: compat_mod.c,v 1.19 2013/03/29 01:02:49 christos Exp $");
|
|
|
|
#ifdef _KERNEL_OPT
|
|
#include "opt_compat_netbsd.h"
|
|
#include "opt_compat_43.h"
|
|
#include "opt_ntp.h"
|
|
#include "opt_sysv.h"
|
|
#include "opt_lfs.h"
|
|
#endif
|
|
|
|
#include <sys/systm.h>
|
|
#include <sys/module.h>
|
|
#include <sys/rwlock.h>
|
|
#include <sys/tty.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/syscallargs.h>
|
|
#include <sys/syscallvar.h>
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
#include <uvm/uvm_object.h>
|
|
|
|
#include <compat/common/compat_util.h>
|
|
#include <compat/common/compat_mod.h>
|
|
|
|
#if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50)
|
|
static struct sysctllog *compat_clog = NULL;
|
|
#endif
|
|
|
|
MODULE(MODULE_CLASS_MISC, compat, NULL);
|
|
|
|
int ttcompat(struct tty *, u_long, void *, int, struct lwp *);
|
|
|
|
#ifdef COMPAT_16
|
|
#if !defined(__amd64__) || defined(COMPAT_NETBSD32)
|
|
#define COMPAT_SIGCONTEXT
|
|
extern char sigcode[], esigcode[];
|
|
struct uvm_object *emul_netbsd_object;
|
|
#endif
|
|
#endif
|
|
|
|
extern krwlock_t exec_lock;
|
|
extern krwlock_t ttcompat_lock;
|
|
|
|
static const struct syscall_package compat_syscalls[] = {
|
|
#if defined(COMPAT_43)
|
|
{ SYS_compat_43_fstat43, 0, (sy_call_t *)compat_43_sys_fstat },
|
|
{ SYS_compat_43_lstat43, 0, (sy_call_t *)compat_43_sys_lstat },
|
|
{ SYS_compat_43_oaccept, 0, (sy_call_t *)compat_43_sys_accept },
|
|
{ SYS_compat_43_ocreat, 0, (sy_call_t *)compat_43_sys_creat },
|
|
{ SYS_compat_43_oftruncate, 0, (sy_call_t *)compat_43_sys_ftruncate },
|
|
{ SYS_compat_43_ogetdirentries, 0, (sy_call_t *)compat_43_sys_getdirentries },
|
|
{ SYS_compat_43_ogetdtablesize, 0, (sy_call_t *)compat_43_sys_getdtablesize },
|
|
{ SYS_compat_43_ogethostid, 0, (sy_call_t *)compat_43_sys_gethostid },
|
|
{ SYS_compat_43_ogethostname, 0, (sy_call_t *)compat_43_sys_gethostname },
|
|
{ SYS_compat_43_ogetkerninfo, 0, (sy_call_t *)compat_43_sys_getkerninfo },
|
|
{ SYS_compat_43_ogetpagesize, 0, (sy_call_t *)compat_43_sys_getpagesize },
|
|
{ SYS_compat_43_ogetpeername, 0, (sy_call_t *)compat_43_sys_getpeername },
|
|
{ SYS_compat_43_ogetrlimit, 0, (sy_call_t *)compat_43_sys_getrlimit },
|
|
{ SYS_compat_43_ogetsockname, 0, (sy_call_t *)compat_43_sys_getsockname },
|
|
{ SYS_compat_43_okillpg, 0, (sy_call_t *)compat_43_sys_killpg },
|
|
{ SYS_compat_43_olseek, 0, (sy_call_t *)compat_43_sys_lseek },
|
|
{ SYS_compat_43_ommap, 0, (sy_call_t *)compat_43_sys_mmap },
|
|
{ SYS_compat_43_oquota, 0, (sy_call_t *)compat_43_sys_quota },
|
|
{ SYS_compat_43_orecv, 0, (sy_call_t *)compat_43_sys_recv },
|
|
{ SYS_compat_43_orecvfrom, 0, (sy_call_t *)compat_43_sys_recvfrom },
|
|
{ SYS_compat_43_orecvmsg, 0, (sy_call_t *)compat_43_sys_recvmsg },
|
|
{ SYS_compat_43_osend, 0, (sy_call_t *)compat_43_sys_send },
|
|
{ SYS_compat_43_osendmsg, 0, (sy_call_t *)compat_43_sys_sendmsg },
|
|
{ SYS_compat_43_osethostid, 0, (sy_call_t *)compat_43_sys_sethostid },
|
|
{ SYS_compat_43_osethostname, 0, (sy_call_t *)compat_43_sys_sethostname },
|
|
{ SYS_compat_43_osetrlimit, 0, (sy_call_t *)compat_43_sys_setrlimit },
|
|
{ SYS_compat_43_osigblock, 0, (sy_call_t *)compat_43_sys_sigblock },
|
|
{ SYS_compat_43_osigsetmask, 0, (sy_call_t *)compat_43_sys_sigsetmask },
|
|
{ SYS_compat_43_osigstack, 0, (sy_call_t *)compat_43_sys_sigstack },
|
|
{ SYS_compat_43_osigvec, 0, (sy_call_t *)compat_43_sys_sigvec },
|
|
{ SYS_compat_43_otruncate, 0, (sy_call_t *)compat_43_sys_truncate },
|
|
{ SYS_compat_43_owait, 0, (sy_call_t *)compat_43_sys_wait },
|
|
{ SYS_compat_43_stat43, 0, (sy_call_t *)compat_43_sys_stat },
|
|
#endif
|
|
|
|
#if defined(COMPAT_09)
|
|
{ SYS_compat_09_ogetdomainname, 0, (sy_call_t *)compat_09_sys_getdomainname },
|
|
{ SYS_compat_09_osetdomainname, 0, (sy_call_t *)compat_09_sys_setdomainname },
|
|
{ SYS_compat_09_ouname, 0, (sy_call_t *)compat_09_sys_uname },
|
|
#endif
|
|
|
|
#if defined(COMPAT_10) && !defined(_LP64)
|
|
# if defined(SYSVMSG)
|
|
{ SYS_compat_10_omsgsys, 0, (sy_call_t *)compat_10_sys_msgsys },
|
|
# endif
|
|
# if defined(SYSVSEM)
|
|
{ SYS_compat_10_osemsys, 0, (sy_call_t *)compat_10_sys_semsys },
|
|
# endif
|
|
# if defined(SYSVSHM)
|
|
{ SYS_compat_10_oshmsys, 0, (sy_call_t *)compat_10_sys_shmsys },
|
|
# endif
|
|
#endif /* defined(COMPAT_10) && !defined(_LP64) */
|
|
|
|
#if defined(COMPAT_12)
|
|
{ SYS_compat_12_fstat12, 0, (sy_call_t *)compat_12_sys_fstat },
|
|
{ SYS_compat_12_getdirentries, 0, (sy_call_t *)compat_12_sys_getdirentries },
|
|
{ SYS_compat_12_lstat12, 0, (sy_call_t *)compat_12_sys_lstat },
|
|
{ SYS_compat_12_msync, 0, (sy_call_t *)compat_12_sys_msync },
|
|
{ SYS_compat_12_oreboot, 0, (sy_call_t *)compat_12_sys_reboot },
|
|
{ SYS_compat_12_oswapon, 0, (sy_call_t *)compat_12_sys_swapon },
|
|
{ SYS_compat_12_stat12, 0, (sy_call_t *)compat_12_sys_stat },
|
|
#endif
|
|
|
|
#if defined(COMPAT_13)
|
|
{ SYS_compat_13_sigaction13, 0, (sy_call_t *)compat_13_sys_sigaction },
|
|
{ SYS_compat_13_sigaltstack13, 0, (sy_call_t *)compat_13_sys_sigaltstack },
|
|
{ SYS_compat_13_sigpending13, 0, (sy_call_t *)compat_13_sys_sigpending },
|
|
{ SYS_compat_13_sigprocmask13, 0, (sy_call_t *)compat_13_sys_sigprocmask },
|
|
{ SYS_compat_13_sigreturn13, 0, (sy_call_t *)compat_13_sys_sigreturn },
|
|
{ SYS_compat_13_sigsuspend13, 0, (sy_call_t *)compat_13_sys_sigsuspend },
|
|
#endif
|
|
|
|
#if defined(COMPAT_14)
|
|
# if defined(SYSVSEM)
|
|
{ SYS_compat_14___semctl, 0, (sy_call_t *)compat_14_sys___semctl },
|
|
# endif
|
|
# if defined(SYSVMSG)
|
|
{ SYS_compat_14_msgctl, 0, (sy_call_t *)compat_14_sys_msgctl },
|
|
# endif
|
|
# if defined(SYSVSHM)
|
|
{ SYS_compat_14_shmctl, 0, (sy_call_t *)compat_14_sys_shmctl },
|
|
# endif
|
|
#endif
|
|
|
|
#if defined(COMPAT_16)
|
|
#if defined(COMPAT_SIGCONTEXT)
|
|
{ SYS_compat_16___sigaction14, 0, (sy_call_t *)compat_16_sys___sigaction14 },
|
|
{ SYS_compat_16___sigreturn14, 0, (sy_call_t *)compat_16_sys___sigreturn14 },
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(COMPAT_20)
|
|
{ SYS_compat_20_fhstatfs, 0, (sy_call_t *)compat_20_sys_fhstatfs },
|
|
{ SYS_compat_20_fstatfs, 0, (sy_call_t *)compat_20_sys_fstatfs },
|
|
{ SYS_compat_20_getfsstat, 0, (sy_call_t *)compat_20_sys_getfsstat },
|
|
{ SYS_compat_20_statfs, 0, (sy_call_t *)compat_20_sys_statfs },
|
|
#endif
|
|
|
|
#if defined(COMPAT_30)
|
|
{ SYS_compat_30___fhstat30, 0, (sy_call_t *)compat_30_sys___fhstat30 },
|
|
{ SYS_compat_30___fstat13, 0, (sy_call_t *)compat_30_sys___fstat13 },
|
|
{ SYS_compat_30___lstat13, 0, (sy_call_t *)compat_30_sys___lstat13 },
|
|
{ SYS_compat_30___stat13, 0, (sy_call_t *)compat_30_sys___stat13 },
|
|
{ SYS_compat_30_fhopen, 0, (sy_call_t *)compat_30_sys_fhopen },
|
|
{ SYS_compat_30_fhstat, 0, (sy_call_t *)compat_30_sys_fhstat },
|
|
{ SYS_compat_30_fhstatvfs1, 0, (sy_call_t *)compat_30_sys_fhstatvfs1 },
|
|
{ SYS_compat_30_getdents, 0, (sy_call_t *)compat_30_sys_getdents },
|
|
{ SYS_compat_30_getfh, 0, (sy_call_t *)compat_30_sys_getfh },
|
|
{ SYS_compat_30_socket, 0, (sy_call_t *)compat_30_sys_socket },
|
|
#endif
|
|
|
|
#if defined(COMPAT_40)
|
|
{ SYS_compat_40_mount, 0, (sy_call_t *)compat_40_sys_mount },
|
|
#endif
|
|
#if defined(COMPAT_50)
|
|
{ SYS_compat_50_wait4, 0, (sy_call_t *)compat_50_sys_wait4 },
|
|
{ SYS_compat_50_mknod, 0, (sy_call_t *)compat_50_sys_mknod },
|
|
{ SYS_compat_50_setitimer, 0, (sy_call_t *)compat_50_sys_setitimer },
|
|
{ SYS_compat_50_getitimer, 0, (sy_call_t *)compat_50_sys_getitimer },
|
|
{ SYS_compat_50_select, 0, (sy_call_t *)compat_50_sys_select },
|
|
{ SYS_compat_50_gettimeofday, 0, (sy_call_t *)compat_50_sys_gettimeofday },
|
|
{ SYS_compat_50_getrusage, 0, (sy_call_t *)compat_50_sys_getrusage },
|
|
{ SYS_compat_50_settimeofday, 0, (sy_call_t *)compat_50_sys_settimeofday },
|
|
{ SYS_compat_50_utimes, 0, (sy_call_t *)compat_50_sys_utimes },
|
|
{ SYS_compat_50_adjtime, 0, (sy_call_t *)compat_50_sys_adjtime },
|
|
#ifdef LFS
|
|
{ SYS_compat_50_lfs_segwait, 0, (sy_call_t *)compat_50_sys_lfs_segwait },
|
|
#endif
|
|
{ SYS_compat_50_futimes, 0, (sy_call_t *)compat_50_sys_futimes },
|
|
{ SYS_compat_50_clock_gettime, 0, (sy_call_t *)compat_50_sys_clock_gettime },
|
|
{ SYS_compat_50_clock_settime, 0, (sy_call_t *)compat_50_sys_clock_settime },
|
|
{ SYS_compat_50_clock_getres, 0, (sy_call_t *)compat_50_sys_clock_getres },
|
|
{ SYS_compat_50_timer_settime, 0, (sy_call_t *)compat_50_sys_timer_settime },
|
|
{ SYS_compat_50_timer_gettime, 0, (sy_call_t *)compat_50_sys_timer_gettime },
|
|
{ SYS_compat_50_nanosleep, 0, (sy_call_t *)compat_50_sys_nanosleep },
|
|
{ SYS_compat_50___sigtimedwait, 0, (sy_call_t *)compat_50_sys___sigtimedwait },
|
|
{ SYS_compat_50_mq_timedsend, 0, (sy_call_t *)compat_50_sys_mq_timedsend },
|
|
{ SYS_compat_50_mq_timedreceive, 0, (sy_call_t *)compat_50_sys_mq_timedreceive },
|
|
{ SYS_compat_50_lutimes, 0, (sy_call_t *)compat_50_sys_lutimes },
|
|
# if defined(SYSVSEM)
|
|
{ SYS_compat_50_____semctl13, 0, (sy_call_t *)compat_50_sys_____semctl13 },
|
|
# endif
|
|
# if defined(SYSVMSG)
|
|
{ SYS_compat_50___msgctl13, 0, (sy_call_t *)compat_50_sys___msgctl13 },
|
|
# endif
|
|
# if defined(SYSVSHM)
|
|
{ SYS_compat_50___shmctl13, 0, (sy_call_t *)compat_50_sys___shmctl13 },
|
|
# endif
|
|
{ SYS_compat_50__lwp_park, 0, (sy_call_t *)compat_50_sys__lwp_park },
|
|
{ SYS_compat_50_kevent, 0, (sy_call_t *)compat_50_sys_kevent },
|
|
{ SYS_compat_50_pselect, 0, (sy_call_t *)compat_50_sys_pselect },
|
|
{ SYS_compat_50_pollts, 0, (sy_call_t *)compat_50_sys_pollts },
|
|
{ SYS_compat_50___stat30, 0, (sy_call_t *)compat_50_sys___stat30 },
|
|
{ SYS_compat_50___fstat30, 0, (sy_call_t *)compat_50_sys___fstat30 },
|
|
{ SYS_compat_50___lstat30, 0, (sy_call_t *)compat_50_sys___lstat30 },
|
|
# if defined(NTP)
|
|
{ SYS_compat_50___ntp_gettime30, 0, (sy_call_t *)compat_50_sys___ntp_gettime30 },
|
|
# endif
|
|
{ SYS_compat_50___fhstat40, 0, (sy_call_t *)compat_50_sys___fhstat40 },
|
|
{ SYS_compat_50_aio_suspend, 0, (sy_call_t *)compat_50_sys_aio_suspend },
|
|
{ SYS_compat_50_quotactl, 0, (sy_call_t *)compat_50_sys_quotactl },
|
|
#endif
|
|
#if defined(COMPAT_60)
|
|
{ SYS_compat_60__lwp_park, 0, (sy_call_t *)compat_60_sys__lwp_park },
|
|
#endif
|
|
{ 0, 0, NULL },
|
|
};
|
|
|
|
static int
|
|
compat_modcmd(modcmd_t cmd, void *arg)
|
|
{
|
|
#ifdef COMPAT_16
|
|
proc_t *p;
|
|
#endif
|
|
int error;
|
|
|
|
switch (cmd) {
|
|
case MODULE_CMD_INIT:
|
|
error = syscall_establish(NULL, compat_syscalls);
|
|
if (error != 0) {
|
|
return error;
|
|
}
|
|
#ifdef COMPAT_43
|
|
KASSERT(ttcompatvec == NULL);
|
|
ttcompatvec = ttcompat;
|
|
#endif
|
|
#ifdef COMPAT_16
|
|
#if defined(COMPAT_SIGCONTEXT)
|
|
KASSERT(emul_netbsd.e_sigobject == NULL);
|
|
rw_enter(&exec_lock, RW_WRITER);
|
|
emul_netbsd.e_sigcode = sigcode;
|
|
emul_netbsd.e_esigcode = esigcode;
|
|
emul_netbsd.e_sigobject = &emul_netbsd_object;
|
|
rw_exit(&exec_lock);
|
|
KASSERT(sendsig_sigcontext_vec == NULL);
|
|
sendsig_sigcontext_vec = sendsig_sigcontext;
|
|
#endif
|
|
#endif
|
|
compat_sysctl_init();
|
|
return 0;
|
|
|
|
case MODULE_CMD_FINI:
|
|
#ifdef COMPAT_16
|
|
/*
|
|
* Ensure sendsig_sigcontext() is not being used.
|
|
* module_lock prevents the flag being set on any
|
|
* further processes while we are here. See
|
|
* sigaction1() for the opposing half.
|
|
*/
|
|
mutex_enter(proc_lock);
|
|
PROCLIST_FOREACH(p, &allproc) {
|
|
if ((p->p_lflag & PL_SIGCOMPAT) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
mutex_exit(proc_lock);
|
|
if (p != NULL) {
|
|
return EBUSY;
|
|
}
|
|
sendsig_sigcontext_vec = NULL;
|
|
#endif
|
|
/* Unlink the system calls. */
|
|
error = syscall_disestablish(NULL, compat_syscalls);
|
|
if (error != 0) {
|
|
return error;
|
|
}
|
|
#ifdef COMPAT_43
|
|
/* Unlink ttcompatvec. */
|
|
if (rw_tryenter(&ttcompat_lock, RW_WRITER)) {
|
|
ttcompatvec = NULL;
|
|
rw_exit(&ttcompat_lock);
|
|
} else {
|
|
error = syscall_establish(NULL, compat_syscalls);
|
|
KASSERT(error == 0);
|
|
return EBUSY;
|
|
}
|
|
#endif
|
|
#ifdef COMPAT_16
|
|
#if defined(COMPAT_SIGCONTEXT)
|
|
/*
|
|
* The sigobject may persist if still in use, but
|
|
* is reference counted so will die eventually.
|
|
*/
|
|
rw_enter(&exec_lock, RW_WRITER);
|
|
if (emul_netbsd_object != NULL) {
|
|
(*emul_netbsd_object->pgops->pgo_detach)
|
|
(emul_netbsd_object);
|
|
}
|
|
emul_netbsd_object = NULL;
|
|
emul_netbsd.e_sigcode = NULL;
|
|
emul_netbsd.e_esigcode = NULL;
|
|
emul_netbsd.e_sigobject = NULL;
|
|
rw_exit(&exec_lock);
|
|
#endif
|
|
#endif /* COMPAT_16 */
|
|
compat_sysctl_fini();
|
|
return 0;
|
|
|
|
default:
|
|
return ENOTTY;
|
|
}
|
|
}
|
|
|
|
void
|
|
compat_sysctl_init(void)
|
|
{
|
|
|
|
#if defined(COMPAT_09) || defined(COMPAT_43)
|
|
compat_sysctl_vfs(&compat_clog);
|
|
#endif
|
|
#if defined(COMPAT_50)
|
|
compat_sysctl_time(&compat_clog);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
compat_sysctl_fini(void)
|
|
{
|
|
|
|
#if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_50)
|
|
sysctl_teardown(&compat_clog);
|
|
#endif
|
|
}
|