summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortedu <tedu@openbsd.org>2003-08-21 18:56:07 +0000
committertedu <tedu@openbsd.org>2003-08-21 18:56:07 +0000
commite20a449d57f00d291866ed3def56b4ad4b4b2b15 (patch)
treee4c1ba408a1da199a7f5d407b6159f680564c9a7
parentfix the offsets in decoding byte rom dd (verified per manual); miod@ ok (diff)
downloadwireguard-openbsd-e20a449d57f00d291866ed3def56b4ad4b4b2b15.tar.xz
wireguard-openbsd-e20a449d57f00d291866ed3def56b4ad4b4b2b15.zip
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@
-rw-r--r--sbin/sysctl/sysctl.c135
-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
9 files changed, 284 insertions, 24 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 9b7c3095ed9..0cf34004c74 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.c,v 1.95 2003/06/11 06:22:15 deraadt Exp $ */
+/* $OpenBSD: sysctl.c,v 1.96 2003/08/21 18:56:07 tedu Exp $ */
/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */
/*
@@ -40,7 +40,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95";
#else
-static char *rcsid = "$OpenBSD: sysctl.c,v 1.95 2003/06/11 06:22:15 deraadt Exp $";
+static char *rcsid = "$OpenBSD: sysctl.c,v 1.96 2003/08/21 18:56:07 tedu Exp $";
#endif
#endif /* not lint */
@@ -206,6 +206,7 @@ int sysctl_seminfo(char *, char **, int *, int, int *);
int sysctl_shminfo(char *, char **, int *, int, int *);
int sysctl_watchdog(char *, char **, int *, int, int *);
int sysctl_sensors(char *, char **, int *, int, int *);
+int sysctl_emul(char *, char *, int);
#ifdef CPU_CHIPSET
int sysctl_chipset(char *, char **, int *, int, int *);
#endif
@@ -430,6 +431,9 @@ parse(char *string, int flags)
if (len < 0)
return;
break;
+ case KERN_EMUL:
+ sysctl_emul(string, newval, flags);
+ return;
}
break;
@@ -1964,6 +1968,133 @@ sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
return (3);
}
+char **emul_names;
+int emul_num;
+void emul_init(void);
+
+int
+sysctl_emul(char *string, char *newval, int flags)
+{
+ int mib[4], enabled, i, old, found = 0;
+ char *head, *target;
+ size_t len;
+
+ emul_init();
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_EMUL;
+ mib[3] = KERN_EMUL_ENABLED;
+ head = "kern.emul.";
+
+ if (aflag || strcmp(string, "kern.emul") == 0) {
+ if (strcmp(string, "kern.emul") == 0 && wflag) {
+ warnx("%s: specification is incomplete", string);
+ return (1);
+ }
+ if (nflag)
+ printf("%d\n", emul_num);
+ else
+ printf("%snemuls = %d\n", head, emul_num);
+ for (i = 0; i < emul_num; i++) {
+ mib[2] = i + 1;
+ len = sizeof(int);
+ if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
+ warn("%s", string);
+ continue;
+ }
+ if (nflag)
+ printf("%d\n", enabled);
+ else
+ printf("%s%s = %d\n", head, emul_names[i],
+ enabled);
+ }
+ return (0);
+ }
+ /* User specified a third level name */
+ target = strrchr(string, '.');
+ target++;
+ if (strcmp(string, "nemuls") == 0) {
+ if (newval) {
+ warnx("Operation not permitted");
+ return (1);
+ }
+ if (nflag)
+ printf("%d\n", emul_num);
+ else
+ printf("%snemuls = %d\n", head, emul_num);
+ return (0);
+ }
+ for (i = 0; i < emul_num; i++) {
+ if (strcmp(target, emul_names[i]))
+ continue;
+ found = 1;
+ mib[2] = i + 1;
+ len = sizeof(int);
+ if (newval) {
+ enabled = atoi(newval);
+ if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
+ warn("%s", string);
+ continue;
+ }
+ if (nflag)
+ printf("%d\n", enabled);
+ else
+ printf("%s%s: %d -> %d\n", head, target, old,
+ enabled);
+ } else {
+ if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
+ warn("%s", string);
+ continue;
+ }
+ if (nflag)
+ printf("%d\n", enabled);
+ else
+ printf("%s%s = %d\n", head, target, enabled);
+ }
+ }
+ if (!found)
+ warnx("third level name %s in kern.emul is invalid",
+ string);
+ return (0);
+
+
+}
+
+void
+emul_init(void)
+{
+ static int done;
+ char string[16];
+ int mib[4], i;
+ size_t len;
+
+ if (done)
+ return;
+ done = 1;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_EMUL;
+ mib[2] = KERN_EMUL_NUM;
+ len = sizeof(int);
+ if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
+ return;
+
+ emul_names = malloc(emul_num * sizeof(char *));
+ if (emul_names == NULL) {
+ warn("emul_init");
+ return;
+ }
+
+ for (i = 0; i < emul_num; i++) {
+ mib[2] = i + 1;
+ mib[3] = 0;
+ len = sizeof(string);
+ if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
+ break;
+ emul_names[i] = strdup(string);
+ }
+}
+
/*
* Scan a list of names searching for a particular name.
*/
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 */