lkml.org 
[lkml]   [1996]   [May]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPatch to binfmt_script to support arbitrary interpreters

Several people seem to have independently suggested the following (including
me), so here it is.

The attached patch (to the old, decrepit 1.3.100 actually) causes a
userland program (/bin/usrexec) to be invoked on unrecognised executable
files. (It's done within binfmt_script to avoid duplicate code, but you
could easily do it as a separate binfmt if you wanted too.)

/bin/usrexec is supposed to look for and invoke a userland interpreter to
execute the "executable".

Also attached is version 0.000001 of such an interpreter that can
recognise windows binaries (seems to work, but it's a hack) and java binaries
and invoke their respective interpreters. Clearly it can be improved.

With this patch, there is no need for all that BINFMT_JAVA stuff in
the kernel.

Cheers,

Dr. Bradley Broom,
School of Data Communications, Email: broom@fit.qut.edu.au
Queensland University of Technology, Bus. : +61 7 3864 2769
GPO Box 2434, Brisbane, 4001, Australia. Fax : +61 7 3221 2384

--- linux/fs/exec.c.old Wed May 15 23:08:00 1996
+++ linux/fs/exec.c Wed May 15 23:08:06 1996
@@ -63,19 +63,24 @@

void binfmt_setup(void)
{
-#ifdef CONFIG_BINFMT_ELF
- init_elf_binfmt();
-#endif
+ /* This cannot be configured out of the kernel */
+ /* Formats are actually tried in the reverse order of
+ * registration, and script format must be the last one
+ * tried.
+ */
+ init_script_binfmt();

#ifdef CONFIG_BINFMT_AOUT
init_aout_binfmt();
#endif

+#ifdef CONFIG_BINFMT_ELF
+ init_elf_binfmt();
+#endif
+
#ifdef CONFIG_BINFMT_JAVA
init_java_binfmt();
#endif
- /* This cannot be configured out of the kernel */
- init_script_binfmt();
}

int register_binfmt(struct linux_binfmt * fmt)
--- linux/fs/binfmt_script.c.old Wed May 15 22:45:51 1996
+++ linux/fs/binfmt_script.c Wed May 15 23:01:49 1996
@@ -11,45 +11,63 @@
#include <linux/malloc.h>
#include <linux/binfmts.h>

+#define _PATH_USREXEC "/bin/usrexec"
+
static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *cp, *interp, *i_name, *i_arg;
int retval;
- if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang))
+
+ if (bprm->sh_bang)
return -ENOEXEC;
- /*
- * This section does the #! interpretation.
- * Sorta complicated, but hopefully it will work. -TYT
- */

bprm->sh_bang++;
- iput(bprm->inode);
- bprm->dont_iput=1;
-
- bprm->buf[127] = '\0';
- if ((cp = strchr(bprm->buf, '\n')) == NULL)
- cp = bprm->buf+127;
- *cp = '\0';
- while (cp > bprm->buf) {
- cp--;
- if ((*cp == ' ') || (*cp == '\t'))
- *cp = '\0';
+ /* Determine interp, i_name, and i_arg.
+ */
+ if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) {
+ strcpy (bprm->buf, _PATH_USREXEC);
+ interp = bprm->buf;
+ if ((i_name = strrchr (bprm->buf, '/')) != NULL)
+ i_name++;
else
- break;
+ i_name = bprm->buf;
+ i_arg = 0;
}
- for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
- if (!cp || *cp == '\0')
- return -ENOEXEC; /* No interpreter name found */
- interp = i_name = cp;
- i_arg = 0;
- for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
- if (*cp == '/')
- i_name = cp+1;
+ else {
+ /*
+ * This section does the #! interpretation.
+ * Sorta complicated, but hopefully it will work. -TYT
+ */
+
+ iput(bprm->inode);
+ bprm->dont_iput=1;
+
+ bprm->buf[127] = '\0';
+ if ((cp = strchr(bprm->buf, '\n')) == NULL)
+ cp = bprm->buf+127;
+ *cp = '\0';
+ while (cp > bprm->buf) {
+ cp--;
+ if ((*cp == ' ') || (*cp == '\t'))
+ *cp = '\0';
+ else
+ break;
+ }
+ for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
+ if (!cp || *cp == '\0')
+ return -ENOEXEC; /* No interpreter name found */
+ interp = i_name = cp;
+ i_arg = 0;
+ for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
+ if (*cp == '/')
+ i_name = cp+1;
+ }
+ while ((*cp == ' ') || (*cp == '\t'))
+ *cp++ = '\0';
+ if (*cp)
+ i_arg = cp;
}
- while ((*cp == ' ') || (*cp == '\t'))
- *cp++ = '\0';
- if (*cp)
- i_arg = cp;
+
/*
* OK, we've parsed out the interpreter name and
* (optional) argument.#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

unsigned char buf[1024];
int len;

int
main (int argc, char *argv[])
{
int fd;

if (argc != 2) {
fprintf (stderr, "Usage: %s filetoexec\n", argv[0]);
exit (1);
}
#if 1
fprintf (stderr, "%s %s\n", argv[0], argv[1]);
#endif
if ((fd = open (argv[1], O_RDONLY)) < 0) {
perror (argv[1]);
exit (1);
}
if ((len = read (fd, buf, sizeof (buf))) < 0) {
perror (argv[1]);
exit (1);
}
close (fd);

/* Extensibility of the following could be easily improved!
*/

/* Don't know about the truth of the following test, but it'll
* do as a hack.
*/
if (buf[0] == 'M' && buf[1] == 'Z') {
execl ("/usr/local/bin/wine", "wine", argv[1], NULL);
perror (argv[1]);
exit (1);
}

if (buf[0] == 0xca && buf[1] == 0xfe && buf[2] == 0xba && buf[3] == 0xbe) {
char * cp = strstr (argv[1], ".class");

if (cp) *cp = '\0';
execl ("/usr/local/bin/java", "java", argv[1], NULL);
perror (argv[1]);
exit (1);
}

fprintf (stderr, "%s: unknown binary format for %s\n", argv[0], argv[1]);
exit (1);
}
\
 
 \ /
  Last update: 2005-03-22 13:37    [W:0.075 / U:0.608 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site