From: Kees Cook <keescook@chromium.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Samuel Dionne-Riel <samuel@dionne-riel.com>,
Oleg Nesterov <oleg@redhat.com>,
Richard Weinberger <richard.weinberger@gmail.com>,
Graham Christensen <graham@grahamc.com>,
Michal Hocko <mhocko@suse.com>,
Andrew Morton <akpm@linux-foundation.org>,
LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH v2] exec: load_script: Allow interpreter argument truncation
Date: Thu, 14 Feb 2019 08:43:31 -0800 [thread overview]
Message-ID: <20190214164331.GA33450@beast> (raw)
While we want to make sure the kernel doesn't attempt to execute a
truncated interpreter path, we must allow the interpreter arguments to
be truncated. Perl, for example, will re-read the script itself to parse
arguments correctly.
This documents the parsing steps, and will fail to exec if the string was
truncated with neither an end-of-line nor any trailing whitespace.
Reported-and-Tested-by: Samuel Dionne-Riel <samuel@dionne-riel.com>
Fixes: 8099b047ecc4 ("exec: load_script: don't blindly truncate shebang string")
Signed-off-by: Kees Cook <keescook@chromium.org>
---
v2:
- fix 1-byte-too-early-bail-out in truncation detection (Oleg)
- add Samuel's "tested" tag
---
fs/binfmt_script.c | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index d0078cbb718b..fedcbf3e1f1c 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -20,6 +20,7 @@ static int load_script(struct linux_binprm *bprm)
char *cp;
struct file *file;
int retval;
+ bool truncated = false, end_of_interp = false;
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
return -ENOEXEC;
@@ -42,32 +43,56 @@ static int load_script(struct linux_binprm *bprm)
fput(bprm->file);
bprm->file = NULL;
+ /*
+ * Truncating interpreter arguments is okay: the interpreter
+ * can re-read the script to parse them on its own. Truncating
+ * the interpreter path itself, though, is bad. Note truncation
+ * here, and check for either newline or start of arguments
+ * below.
+ */
for (cp = bprm->buf+2;; cp++) {
- if (cp >= bprm->buf + BINPRM_BUF_SIZE)
- return -ENOEXEC;
- if (!*cp || (*cp == '\n'))
+ if (!*cp || (*cp == '\n')) {
+ end_of_interp = true;
break;
+ }
+ if (cp == bprm->buf + BINPRM_BUF_SIZE - 1) {
+ truncated = true;
+ break;
+ }
}
*cp = '\0';
+ /* Truncate trailing whitespace */
while (cp > bprm->buf) {
cp--;
- if ((*cp == ' ') || (*cp == '\t'))
+ if ((*cp == ' ') || (*cp == '\t')) {
+ end_of_interp = true;
*cp = '\0';
- else
+ } else
break;
}
+ /* Skip leading whitespace */
for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
if (*cp == '\0')
return -ENOEXEC; /* No interpreter name found */
i_name = cp;
i_arg = NULL;
+ /*
+ * Skip until end of string or finding whitespace which
+ * signals the start of interpreter arguments.
+ */
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
/* nothing */ ;
- while ((*cp == ' ') || (*cp == '\t'))
+ /* Truncate and skip any whitespace in front of arguments */
+ while ((*cp == ' ') || (*cp == '\t')) {
+ end_of_interp = true;
*cp++ = '\0';
+ }
if (*cp)
i_arg = cp;
+ /* Fail exec if the name of the interpreter was cut off. */
+ if (truncated && !end_of_interp)
+ return -ENOEXEC;
/*
* OK, we've parsed out the interpreter name and
* (optional) argument.
--
2.17.1
--
Kees Cook
next reply other threads:[~2019-02-14 16:43 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-14 16:43 Kees Cook [this message]
2019-02-14 17:46 ` [PATCH v2] exec: load_script: Allow interpreter argument truncation Oleg Nesterov
2019-02-14 17:59 ` Linus Torvalds
2019-02-14 18:10 ` Kees Cook
2019-02-14 23:07 ` Linus Torvalds
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190214164331.GA33450@beast \
--to=keescook@chromium.org \
--cc=akpm@linux-foundation.org \
--cc=graham@grahamc.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mhocko@suse.com \
--cc=oleg@redhat.com \
--cc=richard.weinberger@gmail.com \
--cc=samuel@dionne-riel.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.