Blame view
fs/binfmt_script.c
4.19 KB
09c434b8a treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 |
/* * linux/fs/binfmt_script.c * |
96de0e252 Convert files to ... |
5 |
* Copyright (C) 1996 Martin von Löwis |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 |
* original #!-checking implemented by tytso. */ #include <linux/module.h> #include <linux/string.h> #include <linux/stat.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/binfmts.h> #include <linux/init.h> #include <linux/file.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 |
#include <linux/err.h> #include <linux/fs.h> |
b5372fe5d exec: load_script... |
17 |
static inline bool spacetab(char c) { return c == ' ' || c == '\t'; } |
ccbb18b67 exec/binfmt_scrip... |
18 |
static inline const char *next_non_spacetab(const char *first, const char *last) |
b5372fe5d exec: load_script... |
19 20 21 22 23 24 |
{ for (; first <= last; first++) if (!spacetab(*first)) return first; return NULL; } |
ccbb18b67 exec/binfmt_scrip... |
25 |
static inline const char *next_terminator(const char *first, const char *last) |
b5372fe5d exec: load_script... |
26 27 28 29 30 31 |
{ for (; first <= last; first++) if (spacetab(*first) || !*first) return first; return NULL; } |
71613c3b8 get rid of pt_reg... |
32 |
static int load_script(struct linux_binprm *bprm) |
1da177e4c Linux-2.6.12-rc2 |
33 |
{ |
ccbb18b67 exec/binfmt_scrip... |
34 |
const char *i_name, *i_sep, *i_arg, *i_end, *buf_end; |
1da177e4c Linux-2.6.12-rc2 |
35 |
struct file *file; |
1da177e4c Linux-2.6.12-rc2 |
36 |
int retval; |
b5372fe5d exec: load_script... |
37 |
/* Not ours to exec if we don't start with "#!". */ |
d74026986 exec: use -ELOOP ... |
38 |
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) |
1da177e4c Linux-2.6.12-rc2 |
39 |
return -ENOEXEC; |
51f39a1f0 syscalls: impleme... |
40 41 |
/* |
b5372fe5d exec: load_script... |
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
* This section handles parsing the #! line into separate * interpreter path and argument strings. We must be careful * because bprm->buf is not yet guaranteed to be NUL-terminated * (though the buffer will have trailing NUL padding when the * file size was smaller than the buffer size). * * We do not want to exec a truncated interpreter path, so either * we find a newline (which indicates nothing is truncated), or * we find a space/tab/NUL after the interpreter path (which * itself may be preceded by spaces/tabs). Truncating the * arguments is fine: the interpreter can re-read the script to * parse them on its own. */ buf_end = bprm->buf + sizeof(bprm->buf) - 1; |
ccbb18b67 exec/binfmt_scrip... |
56 57 58 59 60 |
i_end = strnchr(bprm->buf, sizeof(bprm->buf), ' '); if (!i_end) { i_end = next_non_spacetab(bprm->buf + 2, buf_end); if (!i_end) |
b5372fe5d exec: load_script... |
61 62 63 64 65 |
return -ENOEXEC; /* Entire buf is spaces/tabs */ /* * If there is no later space/tab/NUL we must assume the * interpreter path is truncated. */ |
ccbb18b67 exec/binfmt_scrip... |
66 |
if (!next_terminator(i_end, buf_end)) |
b5372fe5d exec: load_script... |
67 |
return -ENOEXEC; |
ccbb18b67 exec/binfmt_scrip... |
68 |
i_end = buf_end; |
b5372fe5d exec: load_script... |
69 |
} |
ccbb18b67 exec/binfmt_scrip... |
70 71 72 73 74 75 76 |
/* Trim any trailing spaces/tabs from i_end */ while (spacetab(i_end[-1])) i_end--; /* Skip over leading spaces/tabs */ i_name = next_non_spacetab(bprm->buf+2, i_end); if (!i_name || (i_name == i_end)) |
1da177e4c Linux-2.6.12-rc2 |
77 |
return -ENOEXEC; /* No interpreter name found */ |
ccbb18b67 exec/binfmt_scrip... |
78 79 |
/* Is there an optional argument? */ |
1da177e4c Linux-2.6.12-rc2 |
80 |
i_arg = NULL; |
ccbb18b67 exec/binfmt_scrip... |
81 82 83 84 85 86 87 88 89 90 91 92 |
i_sep = next_terminator(i_name, i_end); if (i_sep && (*i_sep != '\0')) i_arg = next_non_spacetab(i_sep, i_end); /* * If the script filename will be inaccessible after exec, typically * because it is a "/dev/fd/<fd>/.." path against an O_CLOEXEC fd, give * up now (on the assumption that the interpreter will want to load * this file). */ if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) return -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
93 94 95 96 97 98 99 100 101 102 |
/* * OK, we've parsed out the interpreter name and * (optional) argument. * Splice in (1) the interpreter's name for argv[0] * (2) (optional) argument to interpreter * (3) filename of shell script (replace argv[0]) * * This is done in reverse order, because of how the * user environment and arguments are stored. */ |
b6a2fea39 mm: variable leng... |
103 104 105 |
retval = remove_arg_zero(bprm); if (retval) return retval; |
986db2d14 exec: simplify th... |
106 |
retval = copy_string_kernel(bprm->interp, bprm); |
c2315c187 exec: load_script... |
107 108 |
if (retval < 0) return retval; |
1da177e4c Linux-2.6.12-rc2 |
109 |
bprm->argc++; |
ccbb18b67 exec/binfmt_scrip... |
110 |
*((char *)i_end) = '\0'; |
1da177e4c Linux-2.6.12-rc2 |
111 |
if (i_arg) { |
ccbb18b67 exec/binfmt_scrip... |
112 |
*((char *)i_sep) = '\0'; |
986db2d14 exec: simplify th... |
113 |
retval = copy_string_kernel(i_arg, bprm); |
c2315c187 exec: load_script... |
114 115 |
if (retval < 0) return retval; |
1da177e4c Linux-2.6.12-rc2 |
116 117 |
bprm->argc++; } |
986db2d14 exec: simplify th... |
118 |
retval = copy_string_kernel(i_name, bprm); |
c2315c187 exec: load_script... |
119 120 |
if (retval) return retval; |
1da177e4c Linux-2.6.12-rc2 |
121 |
bprm->argc++; |
c2315c187 exec: load_script... |
122 |
retval = bprm_change_interp(i_name, bprm); |
b66c59840 exec: do not leav... |
123 124 |
if (retval < 0) return retval; |
1da177e4c Linux-2.6.12-rc2 |
125 126 127 128 |
/* * OK, now restart the process with the interpreter's dentry. */ |
c2315c187 exec: load_script... |
129 |
file = open_exec(i_name); |
1da177e4c Linux-2.6.12-rc2 |
130 131 |
if (IS_ERR(file)) return PTR_ERR(file); |
bc2bf338d exec: Remove recu... |
132 133 |
bprm->interpreter = file; return 0; |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 137 138 139 140 141 142 |
} static struct linux_binfmt script_format = { .module = THIS_MODULE, .load_binary = load_script, }; static int __init init_script_binfmt(void) { |
8fc3dc5a3 __register_binfmt... |
143 144 |
register_binfmt(&script_format); return 0; |
1da177e4c Linux-2.6.12-rc2 |
145 146 147 148 149 150 151 152 153 154 |
} static void __exit exit_script_binfmt(void) { unregister_binfmt(&script_format); } core_initcall(init_script_binfmt); module_exit(exit_script_binfmt); MODULE_LICENSE("GPL"); |