Back to home page

LXR

 
 

    


0001 /*
0002  *  linux/fs/binfmt_script.c
0003  *
0004  *  Copyright (C) 1996  Martin von Löwis
0005  *  original #!-checking implemented by tytso.
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/string.h>
0010 #include <linux/stat.h>
0011 #include <linux/binfmts.h>
0012 #include <linux/init.h>
0013 #include <linux/file.h>
0014 #include <linux/err.h>
0015 #include <linux/fs.h>
0016 
0017 static int load_script(struct linux_binprm *bprm)
0018 {
0019     const char *i_arg, *i_name;
0020     char *cp;
0021     struct file *file;
0022     char interp[BINPRM_BUF_SIZE];
0023     int retval;
0024 
0025     if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
0026         return -ENOEXEC;
0027 
0028     /*
0029      * If the script filename will be inaccessible after exec, typically
0030      * because it is a "/dev/fd/<fd>/.." path against an O_CLOEXEC fd, give
0031      * up now (on the assumption that the interpreter will want to load
0032      * this file).
0033      */
0034     if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
0035         return -ENOENT;
0036 
0037     /*
0038      * This section does the #! interpretation.
0039      * Sorta complicated, but hopefully it will work.  -TYT
0040      */
0041 
0042     allow_write_access(bprm->file);
0043     fput(bprm->file);
0044     bprm->file = NULL;
0045 
0046     bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
0047     if ((cp = strchr(bprm->buf, '\n')) == NULL)
0048         cp = bprm->buf+BINPRM_BUF_SIZE-1;
0049     *cp = '\0';
0050     while (cp > bprm->buf) {
0051         cp--;
0052         if ((*cp == ' ') || (*cp == '\t'))
0053             *cp = '\0';
0054         else
0055             break;
0056     }
0057     for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
0058     if (*cp == '\0') 
0059         return -ENOEXEC; /* No interpreter name found */
0060     i_name = cp;
0061     i_arg = NULL;
0062     for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
0063         /* nothing */ ;
0064     while ((*cp == ' ') || (*cp == '\t'))
0065         *cp++ = '\0';
0066     if (*cp)
0067         i_arg = cp;
0068     strcpy (interp, i_name);
0069     /*
0070      * OK, we've parsed out the interpreter name and
0071      * (optional) argument.
0072      * Splice in (1) the interpreter's name for argv[0]
0073      *           (2) (optional) argument to interpreter
0074      *           (3) filename of shell script (replace argv[0])
0075      *
0076      * This is done in reverse order, because of how the
0077      * user environment and arguments are stored.
0078      */
0079     retval = remove_arg_zero(bprm);
0080     if (retval)
0081         return retval;
0082     retval = copy_strings_kernel(1, &bprm->interp, bprm);
0083     if (retval < 0) return retval; 
0084     bprm->argc++;
0085     if (i_arg) {
0086         retval = copy_strings_kernel(1, &i_arg, bprm);
0087         if (retval < 0) return retval; 
0088         bprm->argc++;
0089     }
0090     retval = copy_strings_kernel(1, &i_name, bprm);
0091     if (retval) return retval; 
0092     bprm->argc++;
0093     retval = bprm_change_interp(interp, bprm);
0094     if (retval < 0)
0095         return retval;
0096 
0097     /*
0098      * OK, now restart the process with the interpreter's dentry.
0099      */
0100     file = open_exec(interp);
0101     if (IS_ERR(file))
0102         return PTR_ERR(file);
0103 
0104     bprm->file = file;
0105     retval = prepare_binprm(bprm);
0106     if (retval < 0)
0107         return retval;
0108     return search_binary_handler(bprm);
0109 }
0110 
0111 static struct linux_binfmt script_format = {
0112     .module     = THIS_MODULE,
0113     .load_binary    = load_script,
0114 };
0115 
0116 static int __init init_script_binfmt(void)
0117 {
0118     register_binfmt(&script_format);
0119     return 0;
0120 }
0121 
0122 static void __exit exit_script_binfmt(void)
0123 {
0124     unregister_binfmt(&script_format);
0125 }
0126 
0127 core_initcall(init_script_binfmt);
0128 module_exit(exit_script_binfmt);
0129 MODULE_LICENSE("GPL");