diff options
Diffstat (limited to 'fs/binfmt_script.c')
-rw-r--r-- | fs/binfmt_script.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c new file mode 100644 index 000000000000..1edbcca25a73 --- /dev/null +++ b/fs/binfmt_script.c | |||
@@ -0,0 +1,116 @@ | |||
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/slab.h> | ||
12 | #include <linux/binfmts.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/file.h> | ||
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/fs.h> | ||
18 | |||
19 | static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) | ||
20 | { | ||
21 | char *cp, *i_name, *i_arg; | ||
22 | struct file *file; | ||
23 | char interp[BINPRM_BUF_SIZE]; | ||
24 | int retval; | ||
25 | |||
26 | if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang)) | ||
27 | return -ENOEXEC; | ||
28 | /* | ||
29 | * This section does the #! interpretation. | ||
30 | * Sorta complicated, but hopefully it will work. -TYT | ||
31 | */ | ||
32 | |||
33 | bprm->sh_bang++; | ||
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 | remove_arg_zero(bprm); | ||
72 | retval = copy_strings_kernel(1, &bprm->interp, bprm); | ||
73 | if (retval < 0) return retval; | ||
74 | bprm->argc++; | ||
75 | if (i_arg) { | ||
76 | retval = copy_strings_kernel(1, &i_arg, bprm); | ||
77 | if (retval < 0) return retval; | ||
78 | bprm->argc++; | ||
79 | } | ||
80 | retval = copy_strings_kernel(1, &i_name, bprm); | ||
81 | if (retval) return retval; | ||
82 | bprm->argc++; | ||
83 | bprm->interp = interp; | ||
84 | |||
85 | /* | ||
86 | * OK, now restart the process with the interpreter's dentry. | ||
87 | */ | ||
88 | file = open_exec(interp); | ||
89 | if (IS_ERR(file)) | ||
90 | return PTR_ERR(file); | ||
91 | |||
92 | bprm->file = file; | ||
93 | retval = prepare_binprm(bprm); | ||
94 | if (retval < 0) | ||
95 | return retval; | ||
96 | return search_binary_handler(bprm,regs); | ||
97 | } | ||
98 | |||
99 | static struct linux_binfmt script_format = { | ||
100 | .module = THIS_MODULE, | ||
101 | .load_binary = load_script, | ||
102 | }; | ||
103 | |||
104 | static int __init init_script_binfmt(void) | ||
105 | { | ||
106 | return register_binfmt(&script_format); | ||
107 | } | ||
108 | |||
109 | static void __exit exit_script_binfmt(void) | ||
110 | { | ||
111 | unregister_binfmt(&script_format); | ||
112 | } | ||
113 | |||
114 | core_initcall(init_script_binfmt); | ||
115 | module_exit(exit_script_binfmt); | ||
116 | MODULE_LICENSE("GPL"); | ||