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" ]
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to