Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | From | Linus Torvalds <> | Date | Fri, 15 Feb 2019 07:54:48 -0800 | Subject | Re: [PATCH v3] exec: load_script: Do not exec truncated interpreter path |
| |
On Thu, Feb 14, 2019 at 10:15 PM Kees Cook <keescook@chromium.org> wrote: > > The only way we know the interpreter wasn't truncated in the > no-newline case is if we see whitespace after first skipping any > leading whitespace, and it seemed really ugly to add a special scan > there.
No, much easier (and likely better code too), to just use 'memchr()'.
What's wrong with this simple and fairly self-describing patch?
And I'll rather add a few lines due to helper functions with names to make it more legible, rather than code in that already fairly long existing function.
Linus 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 <linux/err.h> #include <linux/fs.h> +/* + * 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--; | ![\](/images/icornerr.gif) |