diff options
author | Jilles Tjoelker <jilles@FreeBSD.org> | 2020-05-30 16:00:49 +0000 |
---|---|---|
committer | Jilles Tjoelker <jilles@FreeBSD.org> | 2020-05-30 16:00:49 +0000 |
commit | e0f5c1387df23c8c4811f5b24a7ef6ecac51a71a (patch) | |
tree | 720522fec5317bf9886be3cf971e5164c6facc5b | |
parent | 51cefda17055328ac1e7ec8456a81ec7600cf8dd (diff) | |
download | src-test2-e0f5c1387df23c8c4811f5b24a7ef6ecac51a71a.tar.gz src-test2-e0f5c1387df23c8c4811f5b24a7ef6ecac51a71a.zip |
Notes
-rw-r--r-- | bin/sh/exec.c | 34 | ||||
-rw-r--r-- | bin/sh/tests/execution/Makefile | 1 | ||||
-rw-r--r-- | bin/sh/tests/execution/shellproc6.0 | 8 |
3 files changed, 42 insertions, 1 deletions
diff --git a/bin/sh/exec.c b/bin/sh/exec.c index cd489a40b9dd..60be83857466 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -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, int idx) } +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; } diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile index 526541d50994..1f7f1c80ae2b 100644 --- a/bin/sh/tests/execution/Makefile +++ b/bin/sh/tests/execution/Makefile @@ -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 diff --git a/bin/sh/tests/execution/shellproc6.0 b/bin/sh/tests/execution/shellproc6.0 new file mode 100644 index 000000000000..1c06bc3b05a9 --- /dev/null +++ b/bin/sh/tests/execution/shellproc6.0 @@ -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" ] |