Package: dash
Version: 0.5.8-2.4
Severity: normal
Tags: patch

Hi!
I'm afraid my patch for RC bug #816313 is somewhat faulty: it may fail to close
a file when executing a hashbang-less script.

Updated version of 
debian/diff/0007-Don-t-execute-binary-files-if-execve-returned-ENOEXE.diff
attached.


Meow!
>From 2eea480dc2e1628f3b3a520c4f229d649f4ef77d Mon Sep 17 00:00:00 2001
From: Adam Borowski <[email protected]>
Date: Tue, 24 Jan 2017 05:11:38 +0100
Subject: [PATCH] Don't execute binary files if execve() returned ENOEXEC.

Both "dash -c foo" and "./foo" are supposed to be able to run hashbang-less
scripts, but attempts to execute common binary files tend to be nasty:
especially both ELF and PE tend to make dash create a bunch of files with
unprintable names, that in turn confuse some tools up to causing data loss.

Thus, let's read the first line and see if it looks like text.  This is a
variant of the approach used by bash and zsh; mksh instead checks for
signatures of a bunch of common file types.

POSIX says: "If the executable file is not a text file, the shell may bypass
this command execution.".

Signed-off-by: Adam Borowski <[email protected]>
---
 src/exec.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/src/exec.c b/src/exec.c
index ec0eadd..19ae752 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -148,6 +148,36 @@ shellexec(char **argv, const char *path, int idx)
 }
 
 
+/*
+ * Check if an executable that just failed with ENOEXEC shouldn't be
+ * considered a script (wrong-arch ELF/PE, junk accidentally set +x, etc).
+ * We check only the first line to allow binaries encapsulated in a shell
+ * script without proper quoting.  The first line, if not a hashbang, is
+ * likely to contain comments; even ancient encodings, at least popular
+ * ones, don't use 0x7f nor values below 0x1f other than whitespace (\t,
+ * \n, \v, \f, \r), ISO/IEC 2022 can have SI, SO and \e.
+ */
+STATIC int file_is_binary(const char *cmd)
+{
+       char buf[128];
+       int fd = open(cmd, O_RDONLY|O_NOCTTY);
+       if (fd == -1)
+               return 1;
+       int len = read(fd, buf, sizeof(buf));
+       close(fd);
+       for (int i = 0; i < len; ++i) {
+               char c = buf[i];
+               if (c >= 0 && c <= 8 ||
+                   c >= 16 && c <= 31 && c != 27 ||
+                   c == 0x7f)
+                       return 1;
+               if (c == '\n')
+                       return 0;
+       }
+       return 0;
+}
+
+
 STATIC void
 tryexec(char *cmd, char **argv, char **envp)
 {
@@ -162,6 +192,8 @@ repeat:
        execve(cmd, argv, envp);
 #endif
        if (cmd != path_bshell && errno == ENOEXEC) {
+               if (file_is_binary(cmd))
+                       return;
                *argv-- = cmd;
                *argv = cmd = path_bshell;
                goto repeat;
-- 
2.11.0

Reply via email to