svn commit: r361647 - in head/bin/sh: . tests/execution

Jilles Tjoelker jilles at FreeBSD.org
Sat May 30 16:00:50 UTC 2020


Author: jilles
Date: Sat May 30 16:00:49 2020
New Revision: 361647
URL: https://svnweb.freebsd.org/changeset/base/361647

Log:
  sh: Allow more scripts without #!
  
  Austin Group bugs #1226 and #1250 changed the requirements for shell scripts
  without #! (POSIX does not specify #!; this is about the shell execution
  when execve(2) returns an [ENOEXEC] error).
  
  POSIX says we shall allow execution if the initial part intended to be
  parsed by the shell consists of characters and does not contain the NUL
  character.  This allows concatenating a shell script (ending with exec or
  exit) and a binary payload.
  
  In order to reject common binary files such as PNG images, check that there
  is a lowercase letter or expansion before the last newline before the NUL
  character, in addition to the check for the newline character suggested by
  POSIX.

Added:
  head/bin/sh/tests/execution/shellproc6.0   (contents, props changed)
Modified:
  head/bin/sh/exec.c
  head/bin/sh/tests/execution/Makefile

Modified: head/bin/sh/exec.c
==============================================================================
--- head/bin/sh/exec.c	Sat May 30 13:39:56 2020	(r361646)
+++ head/bin/sh/exec.c	Sat May 30 16:00:49 2020	(r361647)
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <fcntl.h>
 #include <errno.h>
 #include <paths.h>
+#include <stdbool.h>
 #include <stdlib.h>
 
 /*
@@ -140,6 +141,37 @@ shellexec(char **argv, char **envp, const char *path, 
 }
 
 
+static bool
+isbinary(const char *data, size_t len)
+{
+	const char *nul, *p;
+	bool hasletter;
+
+	nul = memchr(data, '\0', len);
+	if (nul == NULL)
+		return false;
+	/*
+	 * POSIX says we shall allow execution if the initial part intended
+	 * to be parsed by the shell consists of characters and does not
+	 * contain the NUL character. This allows concatenating a shell
+	 * script (ending with exec or exit) and a binary payload.
+	 *
+	 * In order to reject common binary files such as PNG images, check
+	 * that there is a lowercase letter or expansion before the last
+	 * newline before the NUL character, in addition to the check for
+	 * the newline character suggested by POSIX.
+	 */
+	hasletter = false;
+	for (p = data; *p != '\0'; p++) {
+		if ((*p >= 'a' && *p <= 'z') || *p == '$' || *p == '`')
+			hasletter = true;
+		if (hasletter && *p == '\n')
+			return false;
+	}
+	return true;
+}
+
+
 static void
 tryexec(char *cmd, char **argv, char **envp)
 {
@@ -155,7 +187,7 @@ tryexec(char *cmd, char **argv, char **envp)
 		if (in != -1) {
 			n = pread(in, buf, sizeof buf, 0);
 			close(in);
-			if (n > 0 && memchr(buf, '\0', n) != NULL) {
+			if (n > 0 && isbinary(buf, n)) {
 				errno = ENOEXEC;
 				return;
 			}

Modified: head/bin/sh/tests/execution/Makefile
==============================================================================
--- head/bin/sh/tests/execution/Makefile	Sat May 30 13:39:56 2020	(r361646)
+++ head/bin/sh/tests/execution/Makefile	Sat May 30 16:00:49 2020	(r361647)
@@ -59,6 +59,7 @@ ${PACKAGE}FILES+=		shellproc2.0
 ${PACKAGE}FILES+=		shellproc3.0
 ${PACKAGE}FILES+=		shellproc4.0
 ${PACKAGE}FILES+=		shellproc5.0
+${PACKAGE}FILES+=		shellproc6.0
 ${PACKAGE}FILES+=		subshell1.0 subshell1.0.stdout
 ${PACKAGE}FILES+=		subshell2.0
 ${PACKAGE}FILES+=		subshell3.0

Added: head/bin/sh/tests/execution/shellproc6.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/bin/sh/tests/execution/shellproc6.0	Sat May 30 16:00:49 2020	(r361647)
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf 'printf "this "\necho is a test\nexit\n\0' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+[ "`testshellproc`" = "this is a test" ]


More information about the svn-src-head mailing list