Merge branch 'linux-4.21' of git://github.com/skeggsb/linux into drm-fixes
[sfrench/cifs-2.6.git] / fs / binfmt_script.c
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");