From patchwork Tue Feb 7 08:33:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Borowski X-Patchwork-Id: 9559439 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EBE9E60434 for ; Tue, 7 Feb 2017 08:33:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CAE9B262F0 for ; Tue, 7 Feb 2017 08:33:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BFD002818B; Tue, 7 Feb 2017 08:33:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE32A262F0 for ; Tue, 7 Feb 2017 08:33:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752035AbdBGIdW (ORCPT ); Tue, 7 Feb 2017 03:33:22 -0500 Received: from tartarus.angband.pl ([89.206.35.136]:58546 "EHLO tartarus.angband.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751164AbdBGIdV (ORCPT ); Tue, 7 Feb 2017 03:33:21 -0500 Received: from umbar.angband.pl ([2001:6a0:118::6]) by tartarus.angband.pl with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.88) (envelope-from ) id 1cb1DA-0007I4-Ei; Tue, 07 Feb 2017 09:33:19 +0100 Received: from kilobyte by umbar.angband.pl with local (Exim 4.89) (envelope-from ) id 1cb1DA-0003st-1p; Tue, 07 Feb 2017 09:33:16 +0100 From: Adam Borowski To: dash@vger.kernel.org Cc: Adam Borowski Date: Tue, 7 Feb 2017 09:33:07 +0100 Message-Id: <20170207083307.14881-1-kilobyte@angband.pl> X-Mailer: git-send-email 2.11.0 X-SA-Exim-Connect-IP: 2001:6a0:118::6 X-SA-Exim-Mail-From: kilobyte@angband.pl Subject: [PATCH] Don't execute binary files if execve() returned ENOEXEC. X-SA-Exim-Version: 4.2.1 (built Tue, 02 Aug 2016 21:08:31 +0000) X-SA-Exim-Scanned: Yes (on tartarus.angband.pl) Sender: dash-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- This has been applied in Debian. While technically it's only a "may" issue in dash itself, and is triggered by user error (trying to exec files you shouldn't exec), the fallout is nasty enough that the bug was classified as serious. The usual failure mode is to create files with names such as: (per submitter, a PE): 90 d4 f6 (an ELF): 01 b0 40 40 08 01 40 38 02 40 04 03 01 05 40 40 ed ed 01 b0 40 40 f8 40 38 02 40 04 03 01 05 40 40 da da 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;