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)
  18{
  19        const char *i_arg, *i_name;
  20        char *cp;
  21        struct file *file;
  22        int retval;
  23
  24        if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
  25                return -ENOEXEC;
  26
  27        /*
  28         * If the script filename will be inaccessible after exec, typically
  29         * because it is a "/dev/fd/<fd>/.." path against an O_CLOEXEC fd, give
  30         * up now (on the assumption that the interpreter will want to load
  31         * this file).
  32         */
  33        if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
  34                return -ENOENT;
  35
  36        /*
  37         * This section does the #! interpretation.
  38         * Sorta complicated, but hopefully it will work.  -TYT
  39         */
  40
  41        allow_write_access(bprm->file);
  42        fput(bprm->file);
  43        bprm->file = NULL;
  44
  45        bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
  46        if ((cp = strchr(bprm->buf, '\n')) == NULL)
  47                cp = bprm->buf+BINPRM_BUF_SIZE-1;
  48        *cp = '\0';
  49        while (cp > bprm->buf) {
  50                cp--;
  51                if ((*cp == ' ') || (*cp == '\t'))
  52                        *cp = '\0';
  53                else
  54                        break;
  55        }
  56        for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
  57        if (*cp == '\0')
  58                return -ENOEXEC; /* No interpreter name found */
  59        i_name = cp;
  60        i_arg = NULL;
  61        for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
  62                /* nothing */ ;
  63        while ((*cp == ' ') || (*cp == '\t'))
  64                *cp++ = '\0';
  65        if (*cp)
  66                i_arg = cp;
  67        /*
  68         * OK, we've parsed out the interpreter name and
  69         * (optional) argument.
  70         * Splice in (1) the interpreter's name for argv[0]
  71         *           (2) (optional) argument to interpreter
  72         *           (3) filename of shell script (replace argv[0])
  73         *
  74         * This is done in reverse order, because of how the
  75         * user environment and arguments are stored.
  76         */
  77        retval = remove_arg_zero(bprm);
  78        if (retval)
  79                return retval;
  80        retval = copy_strings_kernel(1, &bprm->interp, bprm);
  81        if (retval < 0)
  82                return retval;
  83        bprm->argc++;
  84        if (i_arg) {
  85                retval = copy_strings_kernel(1, &i_arg, bprm);
  86                if (retval < 0)
  87                        return retval;
  88                bprm->argc++;
  89        }
  90        retval = copy_strings_kernel(1, &i_name, bprm);
  91        if (retval)
  92                return retval;
  93        bprm->argc++;
  94        retval = bprm_change_interp(i_name, bprm);
  95        if (retval < 0)
  96                return retval;
  97
  98        /*
  99         * OK, now restart the process with the interpreter's dentry.
 100         */
 101        file = open_exec(i_name);
 102        if (IS_ERR(file))
 103                return PTR_ERR(file);
 104
 105        bprm->file = file;
 106        retval = prepare_binprm(bprm);
 107        if (retval < 0)
 108                return retval;
 109        return search_binary_handler(bprm);
 110}
 111
 112static struct linux_binfmt script_format = {
 113        .module         = THIS_MODULE,
 114        .load_binary    = load_script,
 115};
 116
 117static int __init init_script_binfmt(void)
 118{
 119        register_binfmt(&script_format);
 120        return 0;
 121}
 122
 123static void __exit exit_script_binfmt(void)
 124{
 125        unregister_binfmt(&script_format);
 126}
 127
 128core_initcall(init_script_binfmt);
 129module_exit(exit_script_binfmt);
 130MODULE_LICENSE("GPL");
 131