From patchwork Mon Feb 10 19:30:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374007 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8F70A1395 for ; Mon, 10 Feb 2020 19:31:27 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id EC84A20661 for ; Mon, 10 Feb 2020 19:31:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="hvrKfX5Y" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EC84A20661 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17762-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 11850 invoked by uid 550); 10 Feb 2020 19:31:12 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11811 invoked from network); 10 Feb 2020 19:31:12 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6noGYPwM3SA0qSn1DjhC04WI3GU5Jbgm29601EFLQxY=; b=hvrKfX5YTyjWi1ypYrma3QUvOIzzwx5eP1e5SWnVM7fYdEB7cTXp0VLscQZXxlorII KASkYlwnUbwRoj+rvzhAZPJR542QwWgAtt0bf9LEgpg4gV9JV9tO3B0r5MmgGnJbfqjc KS/hLBOlgW90PWNOGQmPIgcyzMg0ZELj7LhF8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6noGYPwM3SA0qSn1DjhC04WI3GU5Jbgm29601EFLQxY=; b=Yn8xH3qLHmJSLF5Lig8emJqvKrKUJDHhgpRhR10VF5PFPt7knJyzHwUtBK8t8pBMo/ hB13B8L1lw2gKd1QKvNaxyty8k1CnrXep2e3s2OZMOwqc27ED5l+i/cZkUZwD1VjPRSS Eg1diN4EOPyeApw4z3FFJlf5m1xZfUGOcvAlWb7n/r3+avvJwOv6Tns69lIRCRvMlP3q iCWMNbU3rse5QmKyxZxvjeTLxLIyidnUh612rAC44avcuMs2e1CLK56Qx6BphijoBlj6 w0wKeDj5QjbF7zx5EHgh7LMg/0f+MyRznB+QPVsQp6EsEKlJccJkg7dAIz8y09ifhavu LLZA== X-Gm-Message-State: APjAAAU3DDOsmqTzotPMJ+KuoT2VMWHBAy2nKDti8+0CrJtWsmImgnrd g08QLAEN1dWmsZVh/yuR2rATtQ== X-Google-Smtp-Source: APXvYqzRvao2CNFFWbyoxZWSuc7lKKPgMkVudeHRv3oBDW5/WpFR518lDppuCkgzALOGlW3N5WFORw== X-Received: by 2002:a9d:6289:: with SMTP id x9mr2292404otk.8.1581363059840; Mon, 10 Feb 2020 11:30:59 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 1/7] x86/elf: Add table to document READ_IMPLIES_EXEC Date: Mon, 10 Feb 2020 11:30:43 -0800 Message-Id: <20200210193049.64362-2-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 Add a table to document the current behavior of READ_IMPLIES_EXEC in preparation for changing the behavior. Signed-off-by: Kees Cook --- arch/x86/include/asm/elf.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 69c0f892e310..733f69c2b053 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -281,6 +281,25 @@ extern u32 elf_hwcap2; /* * An executable for which elf_read_implies_exec() returns TRUE will * have the READ_IMPLIES_EXEC personality flag set automatically. + * + * The decision process for determining the results are: + * + *              CPU: | lacks NX*  | has NX, ia32     | has NX, x86_64 | + * ELF:              |            |                  |                | + * -------------------------------|------------------|----------------| + * missing GNU_STACK | exec-all   | exec-all         | exec-all       | + * GNU_STACK == RWX  | exec-all   | exec-all         | exec-all       | + * GNU_STACK == RW   | exec-none  | exec-none        | exec-none      | + * + * exec-all : all PROT_READ user mappings are executable, except when + * backed by files on a noexec-filesystem. + * exec-none : only PROT_EXEC user mappings are executable. + * + * *this column has no architectural effect: NX markings are ignored by + * hardware, but may have behavioral effects when "wants X" collides with + * "cannot be X" constraints in memory permission flags, as in + * https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com + * */ #define elf_read_implies_exec(ex, executable_stack) \ (executable_stack != EXSTACK_DISABLE_X) From patchwork Mon Feb 10 19:30:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374017 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 53E531820 for ; Mon, 10 Feb 2020 19:31:46 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id B046E206ED for ; Mon, 10 Feb 2020 19:31:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="T33oewBV" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B046E206ED Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17765-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 12170 invoked by uid 550); 10 Feb 2020 19:31:16 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 12031 invoked from network); 10 Feb 2020 19:31:13 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SoMlqkPW6d6t+DyvhcmYwhC/CLbcIQw6Iq6GyurXq7I=; b=T33oewBV6LwB0gLY4Y/wgyTFEjrMO+tsNjLjNsIx462NvY6k878hEut+t0Dxl2+T2m qFIdoyfwpqsSACJuHqubYuHgW9i9yCone4feFBOegL9ifmir/GKpPSzwOTAIQnR0UiIU XYJjaM8SHWaBn2q9MVLaVWC/Ev/hNh/61qVfU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SoMlqkPW6d6t+DyvhcmYwhC/CLbcIQw6Iq6GyurXq7I=; b=qOPlEy+J6P42PF16HZx4HMan65YuhsjIx0rzgYu+fqHhiGO87/VV9JTAZibS5LhGyf aaDwGbhAGPqlLEjCQ95wJrJJSzDb5HhZgZ+xOnTePS/ilAQYKT0QXaIubyc+IUQCQUd2 FPtnCXRxcU52lpn6UbDINNKLV9wLyRTF8xzUgUn97euel6S8KKipW9S8z5sedPpA6NLb 7eMK10iTetYszzMkX6hpMc8Fbj5ORP8IIO5qYtgQblRXLJplntWCp1r5r0azCOYdIAqY zCbvBfh9pwOiGN2QGIEon4uhtHCrECC/G3L/IopzB1xiyf8KRrs+MolO7cR6KGYBTfPV /gFA== X-Gm-Message-State: APjAAAWKOkICc6CAVoZ7YlIhpzgwJErTGNHhJguMbr2/UfamqWNT8Kl9 nuc4CgQZhMYdJA2qMfXRvfONJg== X-Google-Smtp-Source: APXvYqzYj09UqOIqVmchmtjHU0/10JBletVlAeKEV0PL33eea4MKTG5zvEVavNY7MuTpo2yAvLV8pg== X-Received: by 2002:a05:6830:1353:: with SMTP id r19mr2298000otq.288.1581363061874; Mon, 10 Feb 2020 11:31:01 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 2/7] x86/elf: Split READ_IMPLIES_EXEC from executable GNU_STACK Date: Mon, 10 Feb 2020 11:30:44 -0800 Message-Id: <20200210193049.64362-3-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 The READ_IMPLIES_EXEC work-around was designed for old toolchains that lacked the ELF PT_GNU_STACK marking under the assumption that toolchains that couldn't specify executable permission flags for the stack may not know how to do it correctly for any memory region. This logic is sensible for having ancient binaries coexist in a system with possibly NX memory, but was implemented in a way that equated having a PT_GNU_STACK marked executable as being as "broken" as lacking the PT_GNU_STACK marking entirely. Things like unmarked assembly and stack trampolines may cause PT_GNU_STACK to need an executable bit, but they do not imply all mappings must be executable. This confusion has led to situations where modern programs with explicitly marked executable stack are forced into the READ_IMPLIES_EXEC state when no such thing is needed. (And leads to unexpected failures when mmap()ing regions of device driver memory that wish to disallow VM_EXEC[1].) In looking for other reasons for the READ_IMPLIES_EXEC behavior, Jann Horn noted that glibc thread stacks have always been marked RWX (until 2003 when they started tracking the PT_GNU_STACK flag instead[2]). And musl doesn't support executable stacks at all[3]. As such, no breakage for multithreaded applications is expected from this change. [1] https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com [2] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=54ee14b3882 [3] https://lkml.kernel.org/r/20190423192534.GN23599@brightrain.aerifal.cx Suggested-by: Hector Marco-Gisbert Signed-off-by: Kees Cook --- arch/x86/include/asm/elf.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 733f69c2b053..a7035065377c 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -288,12 +288,13 @@ extern u32 elf_hwcap2; * ELF:              |            |                  |                | * -------------------------------|------------------|----------------| * missing GNU_STACK | exec-all   | exec-all         | exec-all       | - * GNU_STACK == RWX  | exec-all   | exec-all         | exec-all       | + * GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     | * GNU_STACK == RW   | exec-none  | exec-none        | exec-none      | * * exec-all : all PROT_READ user mappings are executable, except when * backed by files on a noexec-filesystem. * exec-none : only PROT_EXEC user mappings are executable. + * exec-stack: only the stack and PROT_EXEC user mappings are executable. * * *this column has no architectural effect: NX markings are ignored by * hardware, but may have behavioral effects when "wants X" collides with @@ -302,7 +303,7 @@ extern u32 elf_hwcap2; * */ #define elf_read_implies_exec(ex, executable_stack) \ - (executable_stack != EXSTACK_DISABLE_X) + (executable_stack == EXSTACK_DEFAULT) struct task_struct; From patchwork Mon Feb 10 19:30:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374013 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D1685109A for ; Mon, 10 Feb 2020 19:31:39 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 36E5220873 for ; Mon, 10 Feb 2020 19:31:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="mqEHj3cJ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 36E5220873 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17764-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 12088 invoked by uid 550); 10 Feb 2020 19:31:14 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11983 invoked from network); 10 Feb 2020 19:31:13 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Hedv3uQpLYtG/8d40iSwsTwWwbRFJKr8vrN4ZiDg04Q=; b=mqEHj3cJctfFXlmy16cRdbd3ZRwBg+PBoqBPYVmqQH/qHbN5NUcjIYDQxGJmRKQ7wa Gh/oTcwv3s+WJTQGeN5oXvRGmYE52sD2Oy62uw9zNjtHK9oLi+CKMUz2V13jB1bNCceN HKebkK1prPWHrTSh29Rcs3l4gWJQcq2tOzhxQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Hedv3uQpLYtG/8d40iSwsTwWwbRFJKr8vrN4ZiDg04Q=; b=NuBv9/hkGLTThOtpp2KdeY1Moh/4UrQL++mhW1QepEIKN7q00aVW+0NkCUWLRIRzEw a++Kp2MCFUtjmQjm3ZN8yzu7ehnz8V0qTgWB194nB5R/5Fg23pOSiLXRNcJSZWhstOI9 KUAZonIzNxQqMnK2PAJv6gk5ufp561WIHjP14a89eD88eOC9Gbd+LCLny5Nk5/wRLarw 12dG2vprX5U8vs++FrG+dyBfS7wax6EIDX29WpiV76AKvQsLvbOMH6PjIgnM9kiH3iW6 +ikDZlP5F/v5B6WR7a4wotWsvxiq8cBAqqwMsWo02BykMUhQ9ZDWNAhsapq2cxNAtUJD Oe5w== X-Gm-Message-State: APjAAAVmUh9O3kJ+HFHjsfUhnnZ4bV422LD/SNGfYuwK09+3Xl0goj4A 7L4GZNcxwR2P/0DcuS2N7hPrgQ== X-Google-Smtp-Source: APXvYqxzrrMjKkyUG9U1mzxeIF/mXf4CdliJjd23xPg8Q25YEpKS/E/iAhQV5XTWVKedZ6gqCTRpxg== X-Received: by 2002:aca:be57:: with SMTP id o84mr419172oif.138.1581363061318; Mon, 10 Feb 2020 11:31:01 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 3/7] x86/elf: Disable automatic READ_IMPLIES_EXEC for 64-bit address spaces Date: Mon, 10 Feb 2020 11:30:45 -0800 Message-Id: <20200210193049.64362-4-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 With modern x86 64-bit environments, there should never be a need for automatic READ_IMPLIES_EXEC, as the architecture is intended to always be execute-bit aware (as in, the default memory protection should be NX unless a region explicitly requests to be executable). There were very old x86_64 systems that lacked the NX bit, but for those, the NX bit is, obviously, unenforceable, so these changes should have no impact on them. Suggested-by: Hector Marco-Gisbert Signed-off-by: Kees Cook --- arch/x86/include/asm/elf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index a7035065377c..c9b7be0bcad3 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -287,7 +287,7 @@ extern u32 elf_hwcap2; *              CPU: | lacks NX*  | has NX, ia32     | has NX, x86_64 | * ELF:              |            |                  |                | * -------------------------------|------------------|----------------| - * missing GNU_STACK | exec-all   | exec-all         | exec-all       | + * missing GNU_STACK | exec-all   | exec-all         | exec-none      | * GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     | * GNU_STACK == RW   | exec-none  | exec-none        | exec-none      | * @@ -303,7 +303,7 @@ extern u32 elf_hwcap2; * */ #define elf_read_implies_exec(ex, executable_stack) \ - (executable_stack == EXSTACK_DEFAULT) + (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT) struct task_struct; From patchwork Mon Feb 10 19:30:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374009 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D57E51395 for ; Mon, 10 Feb 2020 19:31:32 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 3DB3420838 for ; Mon, 10 Feb 2020 19:31:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="L4WYG666" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3DB3420838 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17763-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 12030 invoked by uid 550); 10 Feb 2020 19:31:13 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11812 invoked from network); 10 Feb 2020 19:31:12 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Xgo1yExYE1FoOrHi/q0yB3FWShMft6x5k4WGrQxm170=; b=L4WYG666B6q1Et3bcdlnVISVkOrsiaz/021i2HOtSDO+5jbbvUU8qOhFuAJpImd9Of tHvcCRS71nZ2E2PCYI1v1I7/5Fx8qC14IBkh3bZudUkhVCFVSTRXv68LgS4rolJ8b7NO oy2IjZYniOec+89rewQ3DeqzhHAbfLUi9rvdA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Xgo1yExYE1FoOrHi/q0yB3FWShMft6x5k4WGrQxm170=; b=GCqfVrqBMglOJBotBqwvRtfObmJXJ5mhMPFEGyDJlUHYCi2JJ7kcTX1WF45ll9fpXx elLfRGtYFcJJQhQXxGDo9yPOwohGDiUceXVtEjtHH7imEcx2faFm6iyFy2P9Prb1QArF ov8DDHhOWCCwfy1TTxu+8NRtAtAjov6ZjMowLiFszatzwHqPGEMuker0il7N6YlgKgLm VGCHiOCofBecTCIb7bZMYB3y8AB2yFSgHGMiqKFrQQevLaLvf53aoiDlgKCWPDmDwxb5 ooQBakZgMBhP3ZhHcCr00afQkkIMGhTDYExI797IO9MsLk5JgjeIdYvr3yPnHtqSI0/n u4Ag== X-Gm-Message-State: APjAAAWS6BNNT3xdamTi3c+8Z671bQMWds5yrYf2YPUbY8I2eThPFbQD 77mBDchJQ4nhdza70vAuiofgwA== X-Google-Smtp-Source: APXvYqxrCRbeRObAKsREPcdxJmg1NESdR+jwjL0VLXI5HeLb3NvoJQshGJ4OJNNqOglQAXv1YayQEA== X-Received: by 2002:a9d:6e8f:: with SMTP id a15mr2204441otr.178.1581363060517; Mon, 10 Feb 2020 11:31:00 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 4/7] arm32/64, elf: Add tables to document READ_IMPLIES_EXEC Date: Mon, 10 Feb 2020 11:30:46 -0800 Message-Id: <20200210193049.64362-5-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 Add tables to document the current behavior of READ_IMPLIES_EXEC in preparation for changing the behavior for both arm64 and arm. Signed-off-by: Kees Cook Reviewed-by: Catalin Marinas --- arch/arm/kernel/elf.c | 24 +++++++++++++++++++++--- arch/arm64/include/asm/elf.h | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index 182422981386..2f69cf978fe3 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -78,9 +78,27 @@ void elf_set_personality(const struct elf32_hdr *x) EXPORT_SYMBOL(elf_set_personality); /* - * Set READ_IMPLIES_EXEC if: - * - the binary requires an executable stack - * - we're running on a CPU which doesn't support NX. + * An executable for which elf_read_implies_exec() returns TRUE will + * have the READ_IMPLIES_EXEC personality flag set automatically. + * + * The decision process for determining the results are: + * + *              CPU: | lacks NX*  | has NX | + * ELF:              |            |           | + * -------------------------------|------------| + * missing GNU_STACK | exec-all   | exec-all  | + * GNU_STACK == RWX  | exec-all   | exec-all  | + * GNU_STACK == RW   | exec-all  | exec-none | + * + * exec-all : all PROT_READ user mappings are executable, except when + * backed by files on a noexec-filesystem. + * exec-none : only PROT_EXEC user mappings are executable. + * + * *this column has no architectural effect: NX markings are ignored by + * hardware, but may have behavioral effects when "wants X" collides with + * "cannot be X" constraints in memory permission flags, as in + * https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com + * */ int arm_elf_read_implies_exec(int executable_stack) { diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index b618017205a3..7fc779e3f1ec 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -96,6 +96,26 @@ */ #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) +/* + * An executable for which elf_read_implies_exec() returns TRUE will + * have the READ_IMPLIES_EXEC personality flag set automatically. + * + * The decision process for determining the results are: + * + *             CPU*: | arm32    | arm64 | + * ELF:              |            |            | + * -------------------------------|------------| + * missing GNU_STACK | exec-all   | exec-all   | + * GNU_STACK == RWX  | exec-all   | exec-all   | + * GNU_STACK == RW   | exec-none | exec-none | + * + * exec-all : all PROT_READ user mappings are executable, except when + * backed by files on a noexec-filesystem. + * exec-none : only PROT_EXEC user mappings are executable. + * + * *all arm64 CPUs support NX, so there is no "lacks NX" column. + * + */ #define elf_read_implies_exec(ex,stk) (stk != EXSTACK_DISABLE_X) #define CORE_DUMP_USE_REGSET From patchwork Mon Feb 10 19:30:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374021 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 78F81109A for ; Mon, 10 Feb 2020 19:32:01 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id ACA57206ED for ; Mon, 10 Feb 2020 19:32:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="PoL0XhCM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ACA57206ED Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17767-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 12284 invoked by uid 550); 10 Feb 2020 19:31:19 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 12103 invoked from network); 10 Feb 2020 19:31:15 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vV+4L9n935hAwwy1rny/bKPJmpM6IQkGJafPemnuM6M=; b=PoL0XhCMF5RYylDc0l4IgFMeB8xwO+uVffzPYfytDnFxlYeMxyX/mZuQokiRqvLpeB 3BSmLKsw8Mn0fTOGDf5FiPjNmXvq0HmdnXXBN/WXOAJCOAtbktliwg0Ij4BFjNLNEwz1 LFDL39Nbv292S1gxIrW8F3TJd9vj+dby5RYxI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vV+4L9n935hAwwy1rny/bKPJmpM6IQkGJafPemnuM6M=; b=hMJTAFG7hrq03iLkGWcmAHSwG8WavQjZYFCLpWehs2CfRkfiyaXMhrhPfHTezFWp9h nnJ7F2Zlz+KRkGY2tLakebkSi/3trPzbbT+5IFp3pGlxMbjvansXK6DzrbRv3V4Xdi3/ XhUoC5LC5XZZegFgTa4jZe4kBS/Sm9ItsMYWyhMw1DBb2Vuip9RCXdtiUVPE+/FHxoEp YzjmqEwRVunBDahZle565rLMAuR8DDPaZS0fvOgQRHlaNQoxw9CkAaWRpqKlbuoiqu56 fTEzJCVE5N8Hihgsu75+gzQf6XA28aBMElSLCWxbXo2Nm5/C4A/LWhp1kNqJi/cStPCN hoJQ== X-Gm-Message-State: APjAAAXODFqbhzgngwBwyk9AxeD0u80MoynzqYxRvlSGGl1IgIYtU+U0 Ul1s2c758oXUHl8WwG9Mve0v/w== X-Google-Smtp-Source: APXvYqxxYA/0/Zbqi4Hv0JHtPdrzzbONYFkwCVp0/iu2hk9k8CQImN2sdfiTosdmQZKPTHVPQ7l30Q== X-Received: by 2002:aca:5083:: with SMTP id e125mr424241oib.96.1581363063722; Mon, 10 Feb 2020 11:31:03 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 5/7] arm32/64, elf: Split READ_IMPLIES_EXEC from executable GNU_STACK Date: Mon, 10 Feb 2020 11:30:47 -0800 Message-Id: <20200210193049.64362-6-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 The READ_IMPLIES_EXEC work-around was designed for old toolchains that lacked the ELF PT_GNU_STACK marking under the assumption that toolchains that couldn't specify executable permission flags for the stack may not know how to do it correctly for any memory region. This logic is sensible for having ancient binaries coexist in a system with possibly NX memory, but was implemented in a way that equated having a PT_GNU_STACK marked executable as being as "broken" as lacking the PT_GNU_STACK marking entirely. Things like unmarked assembly and stack trampolines may cause PT_GNU_STACK to need an executable bit, but they do not imply all mappings must be executable. This confusion has led to situations where modern programs with explicitly marked executable stack are forced into the READ_IMPLIES_EXEC state when no such thing is needed. (And leads to unexpected failures when mmap()ing regions of device driver memory that wish to disallow VM_EXEC[1].) In looking for other reasons for the READ_IMPLIES_EXEC behavior, Jann Horn noted that glibc thread stacks have always been marked RWX (until 2003 when they started tracking the PT_GNU_STACK flag instead[2]). And musl doesn't support executable stacks at all[3]. As such, no breakage for multithreaded applications is expected from this change. This changes arm32 and arm64 compat together, to keep behavior the same. [1] https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com [2] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=54ee14b3882 [3] https://lkml.kernel.org/r/20190423192534.GN23599@brightrain.aerifal.cx Suggested-by: Hector Marco-Gisbert Signed-off-by: Kees Cook Reviewed-by: Catalin Marinas --- arch/arm/kernel/elf.c | 5 +++-- arch/arm64/include/asm/elf.h | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index 2f69cf978fe3..6965a673a141 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -87,12 +87,13 @@ EXPORT_SYMBOL(elf_set_personality); * ELF:              |            |           | * -------------------------------|------------| * missing GNU_STACK | exec-all   | exec-all  | - * GNU_STACK == RWX  | exec-all   | exec-all  | + * GNU_STACK == RWX  | exec-all   | exec-stack | * GNU_STACK == RW   | exec-all  | exec-none | * * exec-all : all PROT_READ user mappings are executable, except when * backed by files on a noexec-filesystem. * exec-none : only PROT_EXEC user mappings are executable. + * exec-stack: only the stack and PROT_EXEC user mappings are executable. * * *this column has no architectural effect: NX markings are ignored by * hardware, but may have behavioral effects when "wants X" collides with @@ -102,7 +103,7 @@ EXPORT_SYMBOL(elf_set_personality); */ int arm_elf_read_implies_exec(int executable_stack) { - if (executable_stack != EXSTACK_DISABLE_X) + if (executable_stack == EXSTACK_DEFAULT) return 1; if (cpu_architecture() < CPU_ARCH_ARMv6) return 1; diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 7fc779e3f1ec..03ada29984a7 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -106,17 +106,18 @@ * ELF:              |            |            | * -------------------------------|------------| * missing GNU_STACK | exec-all   | exec-all   | - * GNU_STACK == RWX  | exec-all   | exec-all   | + * GNU_STACK == RWX  | exec-stack | exec-stack | * GNU_STACK == RW   | exec-none | exec-none | * * exec-all : all PROT_READ user mappings are executable, except when * backed by files on a noexec-filesystem. * exec-none : only PROT_EXEC user mappings are executable. + * exec-stack: only the stack and PROT_EXEC user mappings are executable. * * *all arm64 CPUs support NX, so there is no "lacks NX" column. * */ -#define elf_read_implies_exec(ex,stk) (stk != EXSTACK_DISABLE_X) +#define elf_read_implies_exec(ex,stk) (stk == EXSTACK_DEFAULT) #define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE PAGE_SIZE From patchwork Mon Feb 10 19:30:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374019 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C702B109A for ; Mon, 10 Feb 2020 19:31:53 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 2E12320661 for ; Mon, 10 Feb 2020 19:31:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Dq23bl6v" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2E12320661 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17766-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 12233 invoked by uid 550); 10 Feb 2020 19:31:18 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 12094 invoked from network); 10 Feb 2020 19:31:14 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DhYTjIJlfhAdVkQDwNkbgCuN+O7kJMRLXmPZSNfrFMQ=; b=Dq23bl6vQ5GYWu+qXbbm3ywpJuoquMABzduG3ja8SrHuEWakgb5g99LQjU9/o1Dasx BSdy+vt620n5X/zV49LCGyY1+af2KOLd6H9OKdhofiuqC49AzF8MrE82v122cbzl6q+1 5NFBliiePxKLKssh2fiNiQKRiSvwHByvjxNnY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DhYTjIJlfhAdVkQDwNkbgCuN+O7kJMRLXmPZSNfrFMQ=; b=glyeW3Cznbl36ExXtUhZJkXKCPHdIEoRScRcO+pP1NxyjzoFXuca4C+wP3zj21+van lClRLMIAvOphyYf3qDMHUTHwGxJqaKBFg4JP6FIl+z2PR8nEoXQCbqRwGBgS/fZKfLvc SpkZqKFopIrH+TIrcYLXUWKW6iNtwPGN1rADvnugQkagLbdvuZi/5DomoIC8wuYsxi8v X8GyuBDmAN5SzIwhL/Cp4cx5+YG+RPhI172eO/4w9f95C+yDAlR+77rXkmWnCf06gqGH SBsGM/HpctWHmDzIf7FydFxCD0/kY54P02cMXS3/yUneyq+Ha63Dd+4+qpp0zvfFp9R2 Gtlw== X-Gm-Message-State: APjAAAX60M85hctxzvX5Fzjdd6t3WW8AaVdQkVo3QO9wqol626YCd/vH 7WUANJb9+kU1CgY+As9FjFsb8w== X-Google-Smtp-Source: APXvYqwa0CUBeygnsizZAtkXo0YElyu1+Z7uLDxN7c38yNFFZ5699HBdDmcdJAXUU7zBCJHjZcCrcA== X-Received: by 2002:a9d:7508:: with SMTP id r8mr2262030otk.116.1581363063188; Mon, 10 Feb 2020 11:31:03 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 6/7] arm64, elf: Disable automatic READ_IMPLIES_EXEC for 64-bit address spaces Date: Mon, 10 Feb 2020 11:30:48 -0800 Message-Id: <20200210193049.64362-7-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 With arm64 64-bit environments, there should never be a need for automatic READ_IMPLIES_EXEC, as the architecture has always been execute-bit aware (as in, the default memory protection should be NX unless a region explicitly requests to be executable). Suggested-by: Hector Marco-Gisbert Signed-off-by: Kees Cook Reviewed-by: Catalin Marinas --- arch/arm64/include/asm/elf.h | 4 ++-- fs/compat_binfmt_elf.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 03ada29984a7..ea9221ed68a1 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -105,7 +105,7 @@ *             CPU*: | arm32    | arm64 | * ELF:              |            |            | * -------------------------------|------------| - * missing GNU_STACK | exec-all   | exec-all   | + * missing GNU_STACK | exec-all   | exec-none  | * GNU_STACK == RWX  | exec-stack | exec-stack | * GNU_STACK == RW   | exec-none | exec-none | * @@ -117,7 +117,7 @@ * *all arm64 CPUs support NX, so there is no "lacks NX" column. * */ -#define elf_read_implies_exec(ex,stk) (stk == EXSTACK_DEFAULT) +#define compat_elf_read_implies_exec(ex, stk) (stk == EXSTACK_DEFAULT) #define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE PAGE_SIZE diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index aaad4ca1217e..3068d57436b3 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -113,6 +113,11 @@ #define arch_setup_additional_pages compat_arch_setup_additional_pages #endif +#ifdef compat_elf_read_implies_exec +#undef elf_read_implies_exec +#define elf_read_implies_exec compat_elf_read_implies_exec +#endif + /* * Rename a few of the symbols that binfmt_elf.c will define. * These are all local so the names don't really matter, but it From patchwork Mon Feb 10 19:30:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 11374027 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6A96109A for ; Mon, 10 Feb 2020 19:32:09 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 13AC420661 for ; Mon, 10 Feb 2020 19:32:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="kD5EGiWm" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 13AC420661 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-17768-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 13361 invoked by uid 550); 10 Feb 2020 19:31:19 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 12123 invoked from network); 10 Feb 2020 19:31:16 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Dy7V9n1SJWAfsimqdnx79gIWJx+OE4CfcWEJjNElzkw=; b=kD5EGiWmI843sCuCafTUWkInv63C7SrnPb5eYa/PNLKeGUkbgs8l0tKEsrbARmFeO3 WnDV5WSszUbzwfAhGPPrFN3uYkvvUZgZNfPv/RmgJGj1O3LaHMDNKg2LDgAb2xaw9T6a jtQyquGSSoFjFpvv8I0f9WMF2jMQbyTYs6jqo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Dy7V9n1SJWAfsimqdnx79gIWJx+OE4CfcWEJjNElzkw=; b=IbqiZLoey5083EyI8tDjCDM/e3mgov4bqsuuVO38vGHv4lklF/rxyJmKzp7x8+u1lL UO/TsJ7tN5Kv64ZCn4VXWjbXXIqO8lrhXZHyKH6yHiID+awy/er1CsZVDcrZHVNQyi0b CzeKZ7OLBRgCoZF6WrW6SG1udCNP7/hdUZGYwKV20JVVGzxmUAWfpXLxRmbtxy16TG3Q tZL4FlywTHACcMoTUMRpOVBsaa7MndkjmiIfbr4h2mrlr4PVRUSl0ASkXJfWLKShdyva GX5ID1vYUiFcGaaz/E0u+E14R5YK/bER8aDPTvcldG93CiIhBQUDo7/ooX8SJnCXnPeV dtfQ== X-Gm-Message-State: APjAAAVWRAOmSZD2WXh1+/Qz7VAd8RELFtX3C1Y0AxbE7ISIFDRnfypL RzzmIi9uqmENTVOwte3wwj6oow== X-Google-Smtp-Source: APXvYqytQ6Tq8ED/M4IZzD6H8znkZODeLSYS85Lxv1Mg2ykDKGTymMbliK1RJrYqSv3Cgm5yBLjtiw== X-Received: by 2002:a9d:5a09:: with SMTP id v9mr2153543oth.214.1581363064328; Mon, 10 Feb 2020 11:31:04 -0800 (PST) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Hector Marco-Gisbert , Catalin Marinas , Will Deacon , Jason Gunthorpe , Jann Horn , Russell King , x86@kernel.org, kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 7/7] selftests/exec: Add READ_IMPLIES_EXEC tests Date: Mon, 10 Feb 2020 11:30:49 -0800 Message-Id: <20200210193049.64362-8-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200210193049.64362-1-keescook@chromium.org> References: <20200210193049.64362-1-keescook@chromium.org> MIME-Version: 1.0 In order to check the matrix of possible states for handling READ_IMPLIES_EXEC across native, compat, and the state of PT_GNU_STACK, add tests for these execution conditions. Signed-off-by: Kees Cook --- tools/testing/selftests/exec/Makefile | 42 +++++- .../selftests/exec/read_implies_exec.c | 121 ++++++++++++++++++ .../selftests/exec/strip-gnu-stack-bits.c | 34 +++++ .../testing/selftests/exec/strip-gnu-stack.c | 69 ++++++++++ 4 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/exec/read_implies_exec.c create mode 100644 tools/testing/selftests/exec/strip-gnu-stack-bits.c create mode 100644 tools/testing/selftests/exec/strip-gnu-stack.c diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile index 33339e31e365..085d0e4422ea 100644 --- a/tools/testing/selftests/exec/Makefile +++ b/tools/testing/selftests/exec/Makefile @@ -10,7 +10,19 @@ TEST_FILES := Makefile TEST_GEN_PROGS += recursion-depth -EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx* +TEST_GEN_FILES += strip-gnu-stack +TEST_GEN_PROGS += rie-nx-gnu-stack rie-x-gnu-stack rie-missing-gnu-stack + +# While it would be nice to not build "compat" binaries on 32-bit builders, +# there's no harm: they're just redundant to the native binaries, so skip +# performing any detection for now, as it gets complex quickly. +TEST_GEN_PROGS += rie-compat-nx-gnu-stack \ + rie-compat-x-gnu-stack \ + rie-compat-missing-gnu-stack + +EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved \ + $(OUTPUT)/rie-*.new \ + $(OUTPUT)/xxxxx* include ../lib.mk @@ -26,3 +38,31 @@ $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat cp $< $@ chmod -x $@ +$(OUTPUT)/strip-gnu-stack: strip-gnu-stack.c strip-gnu-stack-bits.c + $(CC) $(CFLAGS) -o $@ $< + +$(OUTPUT)/rie-nx-gnu-stack: read_implies_exec.c + $(CC) $(CFLAGS) -Wl,-z,noexecstack -o $@.new $< + readelf -Wl $@.new | grep GNU_STACK | grep -q 'RW ' && \ + mv $@.new $@ +$(OUTPUT)/rie-x-gnu-stack: read_implies_exec.c + $(CC) $(CFLAGS) -Wl,-z,execstack -o $@.new $< + readelf -Wl $@.new | grep GNU_STACK | grep -q 'RWE' && \ + mv $@.new $@ +$(OUTPUT)/rie-missing-gnu-stack: read_implies_exec.c $(OUTPUT)/strip-gnu-stack + $(CC) $(CFLAGS) -o $@.new $< + $(OUTPUT)/strip-gnu-stack $@.new && \ + mv $@.new $@ + +$(OUTPUT)/rie-compat-nx-gnu-stack: read_implies_exec.c + $(CC) -m32 $(CFLAGS) -Wl,-z,noexecstack -o $@.new $< + readelf -Wl $@.new | grep GNU_STACK | grep -q 'RW ' && \ + mv $@.new $@ +$(OUTPUT)/rie-compat-x-gnu-stack: read_implies_exec.c + $(CC) -m32 $(CFLAGS) -Wl,-z,execstack -o $@.new $< + readelf -Wl $@.new | grep GNU_STACK | grep -q 'RWE' && \ + mv $@.new $@ +$(OUTPUT)/rie-compat-missing-gnu-stack: read_implies_exec.c $(OUTPUT)/strip-gnu-stack + $(CC) -m32 $(CFLAGS) -o $@.new $< + $(OUTPUT)/strip-gnu-stack $@.new && \ + mv $@.new $@ diff --git a/tools/testing/selftests/exec/read_implies_exec.c b/tools/testing/selftests/exec/read_implies_exec.c new file mode 100644 index 000000000000..4b253a84dd27 --- /dev/null +++ b/tools/testing/selftests/exec/read_implies_exec.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * This just examines a PROT_READ mapping to report if it see it gain + * PROT_EXEC too (which means that READ_IMPLIES_EXEC has been enabled). + */ +#include +#include +#include +#include +#include +#include +#include + +const char maps_path[] = "/proc/self/maps"; + +int main(int argc, char *argv[]) +{ + char maps_line[1024]; + FILE *maps; + void *region; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + int ret = -1; + int perms = -1; + int vma_64bit; + + region = mmap(NULL, getpagesize(), PROT_READ, flags, -1, 0); + if (region == MAP_FAILED) { + perror("mmap"); + return 128; + } + maps = fopen(maps_path, "r"); + if (!maps) { + perror(maps_path); + ret = 127; + goto out_munmap; + } + + memset(maps_line, 0, sizeof(maps_line)); + while (fgets(maps_line, sizeof(maps_line), maps)) { + unsigned long long low, high; + char *end; + + low = strtoull(maps_line, &end, 16); + if (*end != '-') { + fprintf(stderr, "Missing '-' separator, line: %s", + maps_line); + ret = 126; + goto out_close; + } + end++; + + high = strtoull(end, &end, 16); + if (*end != ' ') { + fprintf(stderr, "Missing ' ' separator, line: %s", + maps_line); + ret = 125; + goto out_close; + } + end++; + + if ((uintptr_t)region >= low && (uintptr_t)region < high) { + perms = 0; + perms |= end[0] == 'r' ? PROT_READ : 0; + perms |= end[1] == 'w' ? PROT_WRITE : 0; + perms |= end[2] == 'x' ? PROT_EXEC : 0; + + break; + } + } + if (perms == -1) { + fprintf(stderr, "Could not find mmap region\n"); + ret = 124; + goto out_close; + } + + vma_64bit = sizeof(void *) == 8; + fprintf(stderr, "%s-bit, ", vma_64bit ? "64" : "32"); + + ret = 1; + if (strstr(argv[0], "missing-gnu-stack")) { + fprintf(stderr, "missing-gnu-stack, "); + + /* Missing PT_GNU_STACK on 64-bit: not READ_IMPLIES_EXEC */ + if (vma_64bit && (perms & PROT_EXEC) == 0) + ret = 0; + /* Missing PT_GNU_STACK on 32-bit enables READ_IMPLIES_EXEC */ + if (!vma_64bit && (perms & PROT_EXEC) == PROT_EXEC) + ret = 0; + } else if (strstr(argv[0], "x-gnu-stack")) { + fprintf(stderr, "executable gnu-stack, "); + + /* X PT_GNU_STACK should always leave READ_IMPLIES_EXEC off */ + if ((perms & PROT_EXEC) == 0) + ret = 0; + } else if (strstr(argv[0], "nx-gnu-stack")) { + fprintf(stderr, "non-executable PT_GNU_STACK, "); + + /* NX PT_GNU_STACK should always leave READ_IMPLIES_EXEC off */ + if ((perms & PROT_EXEC) == 0) + ret = 0; + } else { + fprintf(stderr, "Unknown invocation\n"); + ret = 123; + goto out_close; + } + + fprintf(stderr, "READ_IMPLIES_EXEC is %s: ", + (perms & PROT_EXEC) ? "on" : "off"); + + if (ret) + fprintf(stderr, "FAIL: %s", maps_line); + else + fprintf(stderr, "ok\n"); + +out_close: + fclose(maps); +out_munmap: + munmap(region, getpagesize()); + + return ret; +} diff --git a/tools/testing/selftests/exec/strip-gnu-stack-bits.c b/tools/testing/selftests/exec/strip-gnu-stack-bits.c new file mode 100644 index 000000000000..907e959c3477 --- /dev/null +++ b/tools/testing/selftests/exec/strip-gnu-stack-bits.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * word-size agnostic routines to scan ELF program headers for PT_GNU_STACK + * and rewrite it as PT_NULL to emulate old toolchains that did not include + * the PT_GNU_STACK program header. + */ + +int strip_bits(char *elf, size_t size) +{ + unsigned int i; + Elf_Ehdr *eh; + + eh = (Elf_Ehdr *)elf; + if (sizeof(*eh) > size) { + fprintf(stderr, "Elf Header too small\n"); + return 124; + } + + for (i = 0; i < eh->e_phnum; i++) { + Elf_Phdr *ph = (Elf_Phdr *)(elf + (eh->e_phoff + eh->e_phentsize * i)); + + if (ph->p_type == PT_GNU_STACK) { + ph->p_type = PT_NULL; + return 0; + } + } + + fprintf(stderr, "PT_GNU_STACK missing\n"); + return 123; +} + +#undef strip_bits +#undef Elf_Ehdr +#undef Elf_Phdr diff --git a/tools/testing/selftests/exec/strip-gnu-stack.c b/tools/testing/selftests/exec/strip-gnu-stack.c new file mode 100644 index 000000000000..529e60cf0e6e --- /dev/null +++ b/tools/testing/selftests/exec/strip-gnu-stack.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Converts an ELF's PT_GNU_STACK program header to PT_NULL. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define strip_bits strip64 +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#include "strip-gnu-stack-bits.c" + +#define strip_bits strip32 +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#include "strip-gnu-stack-bits.c" + +int strip(char *elf, size_t size) +{ + if (size < 4 || elf[0] != '\x7f' || strncmp(elf + 1, "ELF", 3) != 0) { + fprintf(stderr, "Not an ELF file\n"); + return 128; + } + switch (elf[EI_CLASS]) { + case ELFCLASS64: + return strip64(elf, size); + case ELFCLASS32: + return strip32(elf, size); + default: + fprintf(stderr, "Unknown EI_CLASS: 0x%02x\n", elf[EI_CLASS]); + return 127; + } +} + +int main(int argc, char *argv[]) +{ + int fd, ret; + struct stat info; + char *elf; + + fd = open(argv[1], O_RDWR); + if (fd < 0) { + perror(argv[1]); + return 1; + } + + if (fstat(fd, &info)) { + perror(argv[1]); + return 2; + } + + elf = mmap(NULL, info.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); + if (elf == MAP_FAILED) { + perror(argv[1]); + return 3; + } + + ret = strip(elf, info.st_size); + + munmap(elf, info.st_size); + close(fd); + return ret; +}