fs/binfmt_script.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 7cde3f46ad26..c9a7afd477a9 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -14,6 +14,24 @@ #include #include +/* + * Do we have whitespace (ignoring leading) between first and last + * (inclusive). This is the "we are truncating the script command + * line" case. + */ +static inline bool tabspc(char c) { return c == ' ' || c == '\t'; } +static inline bool no_tab_or_space(const char *first, const char *last) +{ + /* Skip leading space (and first non-space) */ + while (tabspc(*first++)) + if (first > last) + return false; + while (first <= last) + if (tabspc(*first++)) + return true; + return false; +} + static int load_script(struct linux_binprm *bprm) { const char *i_arg, *i_name; @@ -42,9 +60,12 @@ static int load_script(struct linux_binprm *bprm) fput(bprm->file); bprm->file = NULL; - bprm->buf[BINPRM_BUF_SIZE - 1] = '\0'; - if ((cp = strchr(bprm->buf, '\n')) == NULL) + cp = memchr(bprm->buf, BINPRM_BUF_SIZE, '\n'); + if (!cp) { cp = bprm->buf+BINPRM_BUF_SIZE-1; + if (no_tab_or_space(bprm->buf+2, cp)) + return -ENOEXEC; + } *cp = '\0'; while (cp > bprm->buf) { cp--;