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 17 static 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 for (cp = bprm->buf+2;; cp++) { 46 if (cp >= bprm->buf + BINPRM_BUF_SIZE) 47 return -ENOEXEC; 48 if (!*cp || (*cp == '\n')) 49 break; 50 } 51 *cp = '\0'; 52 53 while (cp > bprm->buf) { 54 cp--; 55 if ((*cp == ' ') || (*cp == '\t')) 56 *cp = '\0'; 57 else 58 break; 59 } 60 for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++); 61 if (*cp == '\0') 62 return -ENOEXEC; /* No interpreter name found */ 63 i_name = cp; 64 i_arg = NULL; 65 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) 66 /* nothing */ ; 67 while ((*cp == ' ') || (*cp == '\t')) 68 *cp++ = '\0'; 69 if (*cp) 70 i_arg = cp; 71 /* 72 * OK, we've parsed out the interpreter name and 73 * (optional) argument. 74 * Splice in (1) the interpreter's name for argv[0] 75 * (2) (optional) argument to interpreter 76 * (3) filename of shell script (replace argv[0]) 77 * 78 * This is done in reverse order, because of how the 79 * user environment and arguments are stored. 80 */ 81 retval = remove_arg_zero(bprm); 82 if (retval) 83 return retval; 84 retval = copy_strings_kernel(1, &bprm->interp, bprm); 85 if (retval < 0) 86 return retval; 87 bprm->argc++; 88 if (i_arg) { 89 retval = copy_strings_kernel(1, &i_arg, bprm); 90 if (retval < 0) 91 return retval; 92 bprm->argc++; 93 } 94 retval = copy_strings_kernel(1, &i_name, bprm); 95 if (retval) 96 return retval; 97 bprm->argc++; 98 retval = bprm_change_interp(i_name, bprm); 99 if (retval < 0) 100 return retval; 101 102 /* 103 * OK, now restart the process with the interpreter's dentry. 104 */ 105 file = open_exec(i_name); 106 if (IS_ERR(file)) 107 return PTR_ERR(file); 108 109 bprm->file = file; 110 retval = prepare_binprm(bprm); 111 if (retval < 0) 112 return retval; 113 return search_binary_handler(bprm); 114 } 115 116 static struct linux_binfmt script_format = { 117 .module = THIS_MODULE, 118 .load_binary = load_script, 119 }; 120 121 static int __init init_script_binfmt(void) 122 { 123 register_binfmt(&script_format); 124 return 0; 125 } 126 127 static void __exit exit_script_binfmt(void) 128 { 129 unregister_binfmt(&script_format); 130 } 131 132 core_initcall(init_script_binfmt); 133 module_exit(exit_script_binfmt); 134 MODULE_LICENSE("GPL"); 135