summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2003-08-21 18:56:08 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2003-08-21 18:56:08 +0000
commit0d5b09054c67f03f088bb749fe3b1e53819a82d8 (patch)
tree5bcf3c6fc7e2695399f960b2ccabc5ae6cdc7bca /sys
parent07999a2beca07715a2095b080aa2444ef6cf1b67 (diff)
emulation is now controlled by sysctl. changes:
add e_flags to struct emul. this stores on/off and native flags. check for emul enabled in check_exec(). gather all the emuls into a emulsw so a sysctl can find them. create sysctl. move maxhdrsiz calcualation into init_main so it cleans up sys_execve codepath. teach sysctl utility to grok kern.emul hierarchy. requested and ok deraadt@ some comments from mickey@
Diffstat (limited to 'sys')
-rw-r--r--sys/compat/linux/linux_exec.c4
-rw-r--r--sys/kern/exec_conf.c72
-rw-r--r--sys/kern/exec_elf.c3
-rw-r--r--sys/kern/init_main.c8
-rw-r--r--sys/kern/kern_exec.c18
-rw-r--r--sys/kern/kern_sysctl.c44
-rw-r--r--sys/sys/proc.h9
-rw-r--r--sys/sys/sysctl.h15
8 files changed, 151 insertions, 22 deletions
diff --git a/sys/compat/linux/linux_exec.c b/sys/compat/linux/linux_exec.c
index 204eca3692a..b0203f6f956 100644
--- a/sys/compat/linux/linux_exec.c
+++ b/sys/compat/linux/linux_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_exec.c,v 1.21 2003/06/21 00:42:58 tedu Exp $ */
+/* $OpenBSD: linux_exec.c,v 1.22 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: linux_exec.c,v 1.13 1996/04/05 00:01:10 christos Exp $ */
/*-
@@ -110,6 +110,7 @@ struct emul emul_linux_aout = {
NULL,
linux_sigcode,
linux_esigcode,
+ 0,
NULL,
linux_e_proc_exec,
linux_e_proc_fork,
@@ -134,6 +135,7 @@ struct emul emul_linux_elf = {
exec_elf32_fixup,
linux_sigcode,
linux_esigcode,
+ 0,
NULL,
linux_e_proc_exec,
linux_e_proc_fork,
diff --git a/sys/kern/exec_conf.c b/sys/kern/exec_conf.c
index 0af97b9e16b..60d92b590d4 100644
--- a/sys/kern/exec_conf.c
+++ b/sys/kern/exec_conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_conf.c,v 1.12 2001/11/14 14:37:22 hugh Exp $ */
+/* $OpenBSD: exec_conf.c,v 1.13 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: exec_conf.c,v 1.16 1995/12/09 05:34:47 cgd Exp $ */
/*
@@ -121,3 +121,73 @@ struct execsw execsw[] = {
};
int nexecs = (sizeof execsw / sizeof(*execsw));
int exec_maxhdrsz;
+
+extern struct emul emul_native, emul_elf32, emul_elf64, emul_aout,
+ emul_bsdos, emul_aout_freebsd, emul_elf_freebsd, emul_hpux,
+ emul_ibcs2, emul_linux_elf, emul_linux_aout, emul_elf64_netbsd,
+ emul_osf1, emul_sunos, emul_svr4, emul_ultrix;
+struct emul *emulsw[] = {
+ &emul_native,
+#ifdef _KERN_DO_ELF
+ &emul_elf32,
+#endif
+#ifdef _KERN_DO_ELF64
+ &emul_elf64,
+#endif
+#if defined (_KERN_DO_AOUT) && defined (COMPAT_AOUT)
+ &emul_aout,
+#endif
+#ifdef COMPAT_BSDOS
+ &emul_bsdos,
+#endif
+#ifdef COMPAT_FREEBSD
+ &emul_aout_freebsd,
+ &emul_elf_freebsd,
+#endif
+#ifdef COMPAT_HPUX
+ &emul_hpux,
+#endif
+#ifdef COMPAT_IBCS2
+ &emul_ibcs2,
+#endif
+#ifdef COMPAT_LINUX
+ &emul_linux_elf,
+ &emul_linux_aout,
+#endif
+#if defined (COMPAT_NETBSD) && defined (_KERN_DO_ELF64)
+ &emul_elf64_netbsd,
+#endif
+#ifdef COMPAT_OSF1
+ &emul_osf1,
+#endif
+#ifdef COMPAT_SUNOS
+ &emul_sunos,
+#endif
+#ifdef COMPAT_SVR4
+ &emul_svr4,
+#endif
+#ifdef COMPAT_ULTRIX
+ &emul_ultrix,
+#endif
+};
+int nemuls = sizeof(emulsw) / sizeof(*emulsw);
+
+void init_exec(void);
+
+void
+init_exec(void)
+{
+ int i;
+
+ /*
+ * figure out the maximum size of an exec header.
+ * XXX should be able to keep LKM code from modifying exec switch
+ * when we're still using it, but...
+ */
+ if (exec_maxhdrsz == 0) {
+ for (i = 0; i < nexecs; i++)
+ if (execsw[i].es_check != NULL
+ && execsw[i].es_hdrsz > exec_maxhdrsz)
+ exec_maxhdrsz = execsw[i].es_hdrsz;
+ }
+}
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c
index 2ff39545f8d..96083e6bfe9 100644
--- a/sys/kern/exec_elf.c
+++ b/sys/kern/exec_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.c,v 1.47 2003/05/17 14:02:06 grange Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.48 2003/08/21 18:56:07 tedu Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
@@ -137,6 +137,7 @@ struct emul ELFNAMEEND(emul) = {
ELFNAME2(exec,fixup),
sigcode,
esigcode,
+ EMUL_ENABLED | EMUL_NATIVE,
};
/*
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index ada370a248e..e9393e2a2bd 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init_main.c,v 1.105 2003/06/02 23:28:05 millert Exp $ */
+/* $OpenBSD: init_main.c,v 1.106 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */
/*
@@ -135,6 +135,7 @@ void start_cleaner(void *);
void start_update(void *);
void start_reaper(void *);
void start_crypto(void *);
+void init_exec(void);
extern char sigcode[], esigcode[];
#ifdef SYSCALL_DEBUG
@@ -159,8 +160,10 @@ struct emul emul_native = {
NULL,
sigcode,
esigcode,
+ EMUL_ENABLED | EMUL_NATIVE,
};
+
/*
* System startup; initialize the world, create process 0, mount root
* filesystem, and fork to create init and pagedaemon. Most of the
@@ -373,6 +376,9 @@ main(framep)
guard[i] = arc4random();
#endif
+ /* init exec and emul */
+ init_exec();
+
/* Start the scheduler */
scheduler_start();
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index af4347fbfe7..8be38c028df 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.80 2003/06/21 00:42:58 tedu Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.81 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -175,6 +175,8 @@ check_exec(p, epp)
if (execsw[i].es_check == NULL)
continue;
newerror = (*execsw[i].es_check)(p, epp);
+ if (!newerror && !(epp->ep_emul->e_flags & EMUL_ENABLED))
+ newerror = ENOEXEC;
/* make sure the first "interesting" error code is saved. */
if (!newerror || error == ENOEXEC)
error = newerror;
@@ -235,7 +237,7 @@ sys_execve(p, v, retval)
syscallarg(char * *) argp;
syscallarg(char * *) envp;
} */ *uap = v;
- int error, i;
+ int error;
struct exec_package pack;
struct nameidata nid;
struct vattr attr;
@@ -259,18 +261,6 @@ sys_execve(p, v, retval)
*/
p->p_flag |= P_INEXEC;
- /*
- * figure out the maximum size of an exec header, if necessary.
- * XXX should be able to keep LKM code from modifying exec switch
- * when we're still using it, but...
- */
- if (exec_maxhdrsz == 0) {
- for (i = 0; i < nexecs; i++)
- if (execsw[i].es_check != NULL
- && execsw[i].es_hdrsz > exec_maxhdrsz)
- exec_maxhdrsz = execsw[i].es_hdrsz;
- }
-
/* init the namei data to point the file user's program name */
NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index a15d511470b..b75ad814560 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.85 2003/08/15 20:32:18 tedu Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.86 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -92,6 +92,7 @@ int sysctl_diskinit(int, struct proc *);
int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
int sysctl_intrcnt(int *, u_int, void *, size_t *);
int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
+int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
/*
* Lock to avoid too many processes vslocking a large amount of memory
@@ -268,6 +269,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
case KERN_SHMINFO:
case KERN_INTRCNT:
case KERN_WATCHDOG:
+ case KERN_EMUL:
break;
default:
return (ENOTDIR); /* overloaded */
@@ -482,6 +484,9 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
case KERN_WATCHDOG:
return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
newp, newlen));
+ case KERN_EMUL:
+ return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
+ newp, newlen));
default:
return (EOPNOTSUPP);
}
@@ -1516,3 +1521,40 @@ sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
}
+
+int
+sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+ void *newp, size_t newlen)
+{
+ int enabled, error;
+ struct emul *e;
+
+ if (name[0] == KERN_EMUL_NUM) {
+ if (namelen != 1)
+ return (ENOTDIR);
+ return (sysctl_rdint(oldp, oldlenp, newp, nemuls));
+ }
+
+ if (namelen != 2)
+ return (ENOTDIR);
+ if (name[0] > nemuls || name[0] < 0)
+ return (EINVAL);
+ e = emulsw[name[0] - 1];
+
+ switch (name[1]) {
+ case KERN_EMUL_NAME:
+ return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
+ case KERN_EMUL_ENABLED:
+ if (e->e_flags & EMUL_NATIVE)
+ return (sysctl_rdint(oldp, oldlenp, newp, 1));
+ else {
+ enabled = (e->e_flags & EMUL_ENABLED);
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &enabled);
+ e->e_flags |= (enabled & EMUL_ENABLED);
+ return (error);
+ }
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 0f2c883c272..c7a01a41188 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.66 2003/08/03 19:25:49 millert Exp $ */
+/* $OpenBSD: proc.h,v 1.67 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -95,12 +95,19 @@ struct emul {
int (*e_fixup)(struct proc *, struct exec_package *);
char *e_sigcode; /* Start of sigcode */
char *e_esigcode; /* End of sigcode */
+ int e_flags; /* Flags, see below */
struct uvm_object *e_sigobject; /* shared sigcode object */
/* Per-process hooks */
void (*e_proc_exec)(struct proc *, struct exec_package *);
void (*e_proc_fork)(struct proc *p, struct proc *parent);
void (*e_proc_exit)(struct proc *);
};
+/* Flags for e_flags */
+#define EMUL_ENABLED 0x0001 /* Allow exec to continue */
+#define EMUL_NATIVE 0x0002 /* Always enabled */
+
+extern struct emul *emulsw[]; /* All emuls in system */
+extern int nemuls; /* Number of emuls */
/*
* Description of a process.
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 64474a4aef9..38d9f3706a7 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.h,v 1.64 2003/06/02 23:28:22 millert Exp $ */
+/* $OpenBSD: sysctl.h,v 1.65 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */
/*
@@ -177,7 +177,8 @@ struct ctlname {
#define KERN_SHMINFO 62 /* struct: SysV struct shminfo */
#define KERN_INTRCNT 63 /* node: interrupt counters */
#define KERN_WATCHDOG 64 /* node: watchdog */
-#define KERN_MAXID 65 /* number of valid kern ids */
+#define KERN_EMUL 65 /* node: emuls */
+#define KERN_MAXID 66 /* number of valid kern ids */
#define CTL_KERN_NAMES { \
{ 0, 0 }, \
@@ -245,9 +246,19 @@ struct ctlname {
{ "shminfo", CTLTYPE_STRUCT }, \
{ "intrcnt", CTLTYPE_NODE }, \
{ "watchdog", CTLTYPE_NODE }, \
+ { "emul", CTLTYPE_NODE }, \
}
/*
+ * KERN_EMUL subtypes.
+ */
+#define KERN_EMUL_NUM 0
+/* Fourth level sysctl names */
+#define KERN_EMUL_NAME 0
+#define KERN_EMUL_ENABLED 1
+
+
+/*
* KERN_PROC subtypes
*/
#define KERN_PROC_ALL 0 /* everything but kernel threads */