linux/fs/binfmt_script.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/binfmt_script.c
   3 *
   4 *  Copyright (C) 1996  Martin von Löwis
   5 *  original #!-checking implemented by tytso.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/string.h>
  10#include <linux/stat.h>
  11#include <linux/binfmts.h>
  12#include <linux/init.h>
  13#include <linux/file.h>
  14#include <linux/err.h>
  15#include <linux/fs.h>
  16
  17static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
  18{
  19        const char *i_arg, *i_name;
  20        char *cp;
  21        struct file *file;
  22        char interp[BINPRM_BUF_SIZE];
  23        int retval;
  24
  25        if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
  26            (bprm->recursion_depth > BINPRM_MAX_RECURSION))
  27                return -ENOEXEC;
  28        /*
  29         * This section does the #! interpretation.
  30         * Sorta complicated, but hopefully it will work.  -TYT
  31         */
  32
  33        bprm->recursion_depth++;
  34        allow_write_access(bprm->file);
  35        fput(bprm->file);
  36        bprm->file = NULL;
  37
  38        bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
  39        if ((cp = strchr(bprm->buf, '\n')) == NULL)
  40                cp = bprm->buf+BINPRM_BUF_SIZE-1;
  41        *cp = '\0';
  42        while (cp > bprm->buf) {
  43                cp--;
  44                if ((*cp == ' ') || (*cp == '\t'))
  45                        *cp = '\0';
  46                else
  47                        break;
  48        }
  49        for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
  50        if (*cp == '\0') 
  51                return -ENOEXEC; /* No interpreter name found */
  52        i_name = cp;
  53        i_arg = NULL;
  54        for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
  55                /* nothing */ ;
  56        while ((*cp == ' ') || (*cp == '\t'))
  57                *cp++ = '\0';
  58        if (*cp)
  59                i_arg = cp;
  60        strcpy (interp, i_name);
  61        /*
  62         * OK, we've parsed out the interpreter name and
  63         * (optional) argument.
  64         * Splice in (1) the interpreter's name for argv[0]
  65         *           (2) (optional) argument to interpreter
  66         *           (3) filename of shell script (replace argv[0])
  67         *
  68         * This is done in reverse order, because of how the
  69         * user environment and arguments are stored.
  70         */
  71        retval = remove_arg_zero(bprm);
  72        if (retval)
  73                return retval;
  74        retval = copy_strings_kernel(1, &bprm->interp, bprm);
  75        if (retval < 0) return retval; 
  76        bprm->argc++;
  77        if (i_arg) {
  78                retval = copy_strings_kernel(1, &i_arg, bprm);
  79                if (retval < 0) return retval; 
  80                bprm->argc++;
  81        }
  82        retval = copy_strings_kernel(1, &i_name, bprm);
  83        if (retval) return retval; 
  84        bprm->argc++;
  85        bprm->interp = interp;
  86
  87        /*
  88         * OK, now restart the process with the interpreter's dentry.
  89         */
  90        file = open_exec(interp);
  91        if (IS_ERR(file))
  92                return PTR_ERR(file);
  93
  94        bprm->file = file;
  95        retval = prepare_binprm(bprm);
  96        if (retval < 0)
  97                return retval;
  98        return search_binary_handler(bprm,regs);
  99}
 100
 101static struct linux_binfmt script_format = {
 102        .module         = THIS_MODULE,
 103        .load_binary    = load_script,
 104};
 105
 106static int __init init_script_binfmt(void)
 107{
 108        return register_binfmt(&script_format);
 109}
 110
 111static void __exit exit_script_binfmt(void)
 112{
 113        unregister_binfmt(&script_format);
 114}
 115
 116core_initcall(init_script_binfmt);
 117module_exit(exit_script_binfmt);
 118MODULE_LICENSE("GPL");
 119