+ exec-load_script-allow-interpreter-argument-truncation.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     Subject: exec: load_script: allow interpreter argument truncation
has been added to the -mm tree.  Its filename is
     exec-load_script-allow-interpreter-argument-truncation.patch

This patch should soon appear at
    http://ozlabs.org/~akpm/mmots/broken-out/exec-load_script-allow-interpreter-argument-truncation.patch
and later at
    http://ozlabs.org/~akpm/mmotm/broken-out/exec-load_script-allow-interpreter-argument-truncation.patch

Before you just go and hit "reply", please:
   a) Consider who else should be cc'ed
   b) Prefer to cc a suitable mailing list as well
   c) Ideally: find the original patch on the mailing list and do a
      reply-to-all to that, adding suitable additional cc's

*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***

The -mm tree is included into linux-next and is updated
there every 3-4 working days

------------------------------------------------------
From: Kees Cook <keescook@xxxxxxxxxxxx>
Subject: exec: load_script: allow interpreter argument truncation

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.

Link: http://lkml.kernel.org/r/20190214164331.GA33450@beast
Fixes: 8099b047ecc4 ("exec: load_script: don't blindly truncate shebang string")
Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
Reported-by: Samuel Dionne-Riel <samuel@xxxxxxxxxxxxxxx>
Tested-by: Samuel Dionne-Riel <samuel@xxxxxxxxxxxxxxx>
Cc: Oleg Nesterov <oleg@xxxxxxxxxx>
Cc: Richard Weinberger <richard.weinberger@xxxxxxxxx>
Cc: Graham Christensen <graham@xxxxxxxxxxx>
Cc: Michal Hocko <mhocko@xxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---

 fs/binfmt_script.c |   37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

--- a/fs/binfmt_script.c~exec-load_script-allow-interpreter-argument-truncation
+++ a/fs/binfmt_script.c
@@ -20,6 +20,7 @@ static int load_script(struct linux_binp
 	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_binp
 	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.
_

Patches currently in -mm which might be from keescook@xxxxxxxxxxxx are

exec-load_script-allow-interpreter-argument-truncation.patch




[Index of Archives]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux