diff options
author | dillon <dillon@FreeBSD.org> | 2000-04-26 20:58:40 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2000-04-26 20:58:40 +0000 |
commit | ce08285d5ac062de6a96e6491313b81bea80ecaa (patch) | |
tree | 9c48fa81d6c9503f7a1fd3b5440dc0d58696221e /sys/alpha/linux/linux_sysvec.c | |
parent | c816580dfb530d84c2396d9f0d10a9f8e44d4ea4 (diff) | |
download | FreeBSD-src-ce08285d5ac062de6a96e6491313b81bea80ecaa.zip FreeBSD-src-ce08285d5ac062de6a96e6491313b81bea80ecaa.tar.gz |
Fix #! script exec under linux emulation. If a script is exec'd from a
program running under linux emulation, the script binary is checked for
in /compat/linux first. Without this patch the wrong script binary
(i.e. the FreeBSD binary) will be run instead of the linux binary.
For example, #!/bin/sh, thus breaking out of linux compatibility mode.
This solves a number of problems people have had installing linux
software on FreeBSD boxes.
Diffstat (limited to 'sys/alpha/linux/linux_sysvec.c')
-rw-r--r-- | sys/alpha/linux/linux_sysvec.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index bd2211b..0adf0ab 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -55,9 +55,16 @@ #include <i386/linux/linux.h> #include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); +#if BYTE_ORDER == LITTLE_ENDIAN +#define SHELLMAGIC 0x2123 /* #! */ +#else +#define SHELLMAGIC 0x2321 +#endif + extern char linux_sigcode[]; extern int linux_szsigcode; @@ -401,6 +408,50 @@ linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) *params = NULL; /* no copyin */ } +/* + * If a linux binary is exec'ing something, try this image activator + * first. We override standard shell script execution in order to + * be able to modify the interpreter path. We only do this if a linux + * binary is doing the exec, so we do not create an EXEC module for it. + */ +static int exec_linux_imgact_try __P((struct image_params *iparams)); + +static int +exec_linux_imgact_try(imgp) + struct image_params *imgp; +{ + const char *head = (const char *)imgp->image_header; + int error = -1; + + /* + * The interpreter for shell scripts run from a linux binary needs + * to be located in /compat/linux if possible in order to recursively + * maintain linux path emulation. + */ + if (((const short *)head)[0] == SHELLMAGIC) { + /* + * Run our normal shell image activator. If it succeeds attempt + * to use the alternate path for the interpreter. If an alternate + * path is found, use our stringspace to store it. + */ + if ((error = exec_shell_imgact(imgp)) == 0) { + char *rpath = NULL; + + linux_emul_find(imgp->proc, NULL, linux_emul_path, + imgp->interpreter_name, &rpath, 0); + if (rpath != imgp->interpreter_name) { + int len = strlen(rpath) + 1; + + if (len <= MAXSHELLCMDLEN) { + memcpy(imgp->interpreter_name, rpath, len); + } + free(rpath, M_TEMP); + } + } + } + return(error); +} + struct sysentvec linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, @@ -416,7 +467,8 @@ struct sysentvec linux_sysvec = { &linux_szsigcode, linux_prepsyscall, "Linux a.out", - aout_coredump + aout_coredump, + exec_linux_imgact_try }; struct sysentvec elf_linux_sysvec = { @@ -434,7 +486,8 @@ struct sysentvec elf_linux_sysvec = { &linux_szsigcode, linux_prepsyscall, "Linux ELF", - elf_coredump + elf_coredump, + exec_linux_imgact_try }; static Elf32_Brandinfo linux_brand = { |