0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/string.h>
0011 #include <linux/stat.h>
0012 #include <linux/binfmts.h>
0013 #include <linux/init.h>
0014 #include <linux/file.h>
0015 #include <linux/err.h>
0016 #include <linux/fs.h>
0017
0018 static inline bool spacetab(char c) { return c == ' ' || c == '\t'; }
0019 static inline const char *next_non_spacetab(const char *first, const char *last)
0020 {
0021 for (; first <= last; first++)
0022 if (!spacetab(*first))
0023 return first;
0024 return NULL;
0025 }
0026 static inline const char *next_terminator(const char *first, const char *last)
0027 {
0028 for (; first <= last; first++)
0029 if (spacetab(*first) || !*first)
0030 return first;
0031 return NULL;
0032 }
0033
0034 static int load_script(struct linux_binprm *bprm)
0035 {
0036 const char *i_name, *i_sep, *i_arg, *i_end, *buf_end;
0037 struct file *file;
0038 int retval;
0039
0040
0041 if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
0042 return -ENOEXEC;
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 buf_end = bprm->buf + sizeof(bprm->buf) - 1;
0059 i_end = strnchr(bprm->buf, sizeof(bprm->buf), '\n');
0060 if (!i_end) {
0061 i_end = next_non_spacetab(bprm->buf + 2, buf_end);
0062 if (!i_end)
0063 return -ENOEXEC;
0064
0065
0066
0067
0068 if (!next_terminator(i_end, buf_end))
0069 return -ENOEXEC;
0070 i_end = buf_end;
0071 }
0072
0073 while (spacetab(i_end[-1]))
0074 i_end--;
0075
0076
0077 i_name = next_non_spacetab(bprm->buf+2, i_end);
0078 if (!i_name || (i_name == i_end))
0079 return -ENOEXEC;
0080
0081
0082 i_arg = NULL;
0083 i_sep = next_terminator(i_name, i_end);
0084 if (i_sep && (*i_sep != '\0'))
0085 i_arg = next_non_spacetab(i_sep, i_end);
0086
0087
0088
0089
0090
0091
0092
0093 if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
0094 return -ENOENT;
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 retval = remove_arg_zero(bprm);
0107 if (retval)
0108 return retval;
0109 retval = copy_string_kernel(bprm->interp, bprm);
0110 if (retval < 0)
0111 return retval;
0112 bprm->argc++;
0113 *((char *)i_end) = '\0';
0114 if (i_arg) {
0115 *((char *)i_sep) = '\0';
0116 retval = copy_string_kernel(i_arg, bprm);
0117 if (retval < 0)
0118 return retval;
0119 bprm->argc++;
0120 }
0121 retval = copy_string_kernel(i_name, bprm);
0122 if (retval)
0123 return retval;
0124 bprm->argc++;
0125 retval = bprm_change_interp(i_name, bprm);
0126 if (retval < 0)
0127 return retval;
0128
0129
0130
0131
0132 file = open_exec(i_name);
0133 if (IS_ERR(file))
0134 return PTR_ERR(file);
0135
0136 bprm->interpreter = file;
0137 return 0;
0138 }
0139
0140 static struct linux_binfmt script_format = {
0141 .module = THIS_MODULE,
0142 .load_binary = load_script,
0143 };
0144
0145 static int __init init_script_binfmt(void)
0146 {
0147 register_binfmt(&script_format);
0148 return 0;
0149 }
0150
0151 static void __exit exit_script_binfmt(void)
0152 {
0153 unregister_binfmt(&script_format);
0154 }
0155
0156 core_initcall(init_script_binfmt);
0157 module_exit(exit_script_binfmt);
0158 MODULE_LICENSE("GPL");