diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2003-08-21 18:56:08 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2003-08-21 18:56:08 +0000 |
commit | 0d5b09054c67f03f088bb749fe3b1e53819a82d8 (patch) | |
tree | 5bcf3c6fc7e2695399f960b2ccabc5ae6cdc7bca /sys | |
parent | 07999a2beca07715a2095b080aa2444ef6cf1b67 (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.c | 4 | ||||
-rw-r--r-- | sys/kern/exec_conf.c | 72 | ||||
-rw-r--r-- | sys/kern/exec_elf.c | 3 | ||||
-rw-r--r-- | sys/kern/init_main.c | 8 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 18 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 44 | ||||
-rw-r--r-- | sys/sys/proc.h | 9 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 15 |
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 */ |