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: 11374005 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 E419D1820 for ; Mon, 10 Feb 2020 19:31:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BC53F215A4 for ; Mon, 10 Feb 2020 19:31:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="hvrKfX5Y" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727671AbgBJTbB (ORCPT ); Mon, 10 Feb 2020 14:31:01 -0500 Received: from mail-ot1-f67.google.com ([209.85.210.67]:37688 "EHLO mail-ot1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727639AbgBJTbB (ORCPT ); Mon, 10 Feb 2020 14:31:01 -0500 Received: by mail-ot1-f67.google.com with SMTP id d3so7577984otp.4 for ; Mon, 10 Feb 2020 11:31:00 -0800 (PST) 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=pnifBFGk9uwgt1FTgNNrLoiosY+Ca6ahODbdfhCuZwpXCqyDU/4mNshdl7uQTeOmkM 3cDEPbQ0GWG8R+i6rRzKf5pVsZD4d80CGKWHozpJ6+DYaNkQ/qBf0uWuM5W6wsaxFU2V /BBIJcfvU0ZAG5r6VD6UH3mmbWsIlMrhYN9O0zxyhDoPrs3OBK+hfym38rlhYw0ucdbw a9WrgiauTGRFfiQeCloJvX+nAvJjJUvfKlYSV8VF0vDxlYE1ubhJJ6PDdSeTQ7c7f8Ki W3mtoTeMqY6rtw/7dvCF5aZPXeMqjKSZ9igYOIA6kS3GNs5gPUiWD8Af8rIJqJ4VU5WG jQjA== X-Gm-Message-State: APjAAAUMiljs2uLaZkKvrJ9uWDoC2GnUdaOqrYHkytylvaptwPMLwA1A eng6TRR56PQ/u1ZJ57pXDVwCPQ== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id y6sm359826oti.44.2020.02.10.11.30.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2020 11:30:58 -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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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: 11373985 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 9256E109A for ; Mon, 10 Feb 2020 19:31:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 72700208C4 for ; Mon, 10 Feb 2020 19:31:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="T33oewBV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727705AbgBJTbC (ORCPT ); Mon, 10 Feb 2020 14:31:02 -0500 Received: from mail-ot1-f67.google.com ([209.85.210.67]:39348 "EHLO mail-ot1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727695AbgBJTbC (ORCPT ); Mon, 10 Feb 2020 14:31:02 -0500 Received: by mail-ot1-f67.google.com with SMTP id 77so7547643oty.6 for ; Mon, 10 Feb 2020 11:31:02 -0800 (PST) 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=JFwAcbcBeIXivzqO5dVoHMJ6B9Zodlpp5BgtZZ/ci2+1phdW5nRMlx7/SeSTWsBTDP xlfut9ZFtWIxAnRePv+BxaM4DiOc7uY0viRjK6uJZzghgA4txTFX8uyt7y6thXlF0NZq Kpboqh7sYvAhgd9zAImboKq7ogNlSr3isEkXvMjVR6cWu9W2oYxmcPc0hGtgeQfOJOqW yy+w2I6yoSD/J3udJhKSy6nI0HbPBM+lCScgzpLminZYwVU4t8DzqnWfDfTl/8Nr6quj LQwfDPshUgPHzvCqZ+Z9G9320lguQSMCMA77yZoBeA+7HfGTcFkum6tz9wWgm0dEuZeo CEQQ== X-Gm-Message-State: APjAAAWBTQHgHmOacJQCprTqh9MqXIkDmUmTqShZT9WWaKlNXf83dnvw smIwIdWQfO2/PQklGmt5Lc2+OQ== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id m19sm362991otn.47.2020.02.10.11.30.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2020 11:30:58 -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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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: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: 11373989 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 588251395 for ; Mon, 10 Feb 2020 19:31:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 39D6F215A4 for ; Mon, 10 Feb 2020 19:31:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="L4WYG666" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727707AbgBJTbD (ORCPT ); Mon, 10 Feb 2020 14:31:03 -0500 Received: from mail-ot1-f65.google.com ([209.85.210.65]:46190 "EHLO mail-ot1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727692AbgBJTbC (ORCPT ); Mon, 10 Feb 2020 14:31:02 -0500 Received: by mail-ot1-f65.google.com with SMTP id g64so7521617otb.13 for ; Mon, 10 Feb 2020 11:31:00 -0800 (PST) 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=p04vkuCAlGXjT6423ohmZ0eXyJ+bOhyT4CxoZquJFEaoWDlpzstsK+TZTofYo2ELWI fWoIUDI9g9aNOaN+P3dXV3hVCIah0fpbdWFS8tEmHCHX+Ch1UzXm6hbflInOn7AHptyf N27cfYGk1T6TN8jYVgQ5Ye70jgrWyGH0Q6fJoatNDkeUCoQ3a5cPR1inWPFI4Mer5mPo /1cx9Pae3D6vu8XHWQoQrdIkDoccF49JVYmiOMidqsegt50eLmG4ept6czv6pgsZu3Lr ZNI1YpuGFBdRjPRz1hxqif9Nr1JtCj5dqClIXeiOkNhrD0Gtsb3wXt0gG9bn8fEHKQ9j cJfg== X-Gm-Message-State: APjAAAVo3yjyQADS7x5Wfo7evzYOFjptasNGZu7hwSjCijaaKBGnGnMN YHWpQXP1NrhmMQBL6dRBnXMP/g== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id b145sm356027oii.31.2020.02.10.11.30.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2020 11:30:58 -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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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: 11374001 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 5E88D1395 for ; Mon, 10 Feb 2020 19:31:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3FB1A20838 for ; Mon, 10 Feb 2020 19:31:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="PoL0XhCM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727705AbgBJTbT (ORCPT ); Mon, 10 Feb 2020 14:31:19 -0500 Received: from mail-oi1-f193.google.com ([209.85.167.193]:34164 "EHLO mail-oi1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727726AbgBJTbE (ORCPT ); Mon, 10 Feb 2020 14:31:04 -0500 Received: by mail-oi1-f193.google.com with SMTP id l136so10359863oig.1 for ; Mon, 10 Feb 2020 11:31:04 -0800 (PST) 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=PqjYj8Tq0eqhUsUn4oJVZgETRNekCBskn8uY6kxU0/jtdfn9vR/TIt28z1mQvOp73f yQ/8TaNWL/ePmJCnUSqYeugopZ2QiG7lc+ug981lNleIJdWz60jcgrhkO5GQqMTQMJ7D 14ZsV9c36ZUudYNyRKrcPmHhmzd28yKcACj2PeMLr6ACMPIutiejvoZTyT+6nRxTFse6 8GI0Itf0BaBRtiRTbgqU+Y84nKdUadz7++u9GWP4GiXCcsP9NToD+8nKr3loKcU6KUlW t2ymHIdk/brvaCjuyjEhRF5SgkkR+/KG5uAcOqZdSZLL4QZP8XnThOrDMHqmhVBJoHkR gXbQ== X-Gm-Message-State: APjAAAXchh2XfVo6kYmmY/8irZkcQHnZ94IFpXgbIBKCZCbFiqp6ROQ2 3/1Xt/Azq1SH4MfTqZkt42lyPQ== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id f1sm370846otq.4.2020.02.10.11.31.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2020 11:31:02 -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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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: 11373991 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 0D0991395 for ; Mon, 10 Feb 2020 19:31:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E2DE52173E for ; Mon, 10 Feb 2020 19:31:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Dq23bl6v" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727772AbgBJTbF (ORCPT ); Mon, 10 Feb 2020 14:31:05 -0500 Received: from mail-ot1-f68.google.com ([209.85.210.68]:46199 "EHLO mail-ot1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727761AbgBJTbF (ORCPT ); Mon, 10 Feb 2020 14:31:05 -0500 Received: by mail-ot1-f68.google.com with SMTP id g64so7521792otb.13 for ; Mon, 10 Feb 2020 11:31:03 -0800 (PST) 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=UVHbo/IC2e0TPlde8LxvDQdi017EMunVG8sNmbD28QwjonGmi7Lt58rT05USUMURx4 zjAfgfnzJ9/uF7sWupgRgS3RP1zRByREkxXqMTLHw6T47SCmf+aQ4uXo7n3co7EDqeSl kR0dDn+JqcLHUzmDWk9Pb9sD0TcvMo0UgKT6Xo4bfsyQJBgYiNgb9+9CZ1dCHXSsl7TH dIzdJ8AlxDz99N3KdrgEB8XqBO72UNZ/CT4on2OhRm7Xyr1sTH4PcF0kB2uxTD0BfVfJ C0GJvQJgfE/QnJXgiamdIpcWN5lvU1+zq9wfuxSDcrHIVFSmJyshyBs7l7aZATaQbbl6 qkgw== X-Gm-Message-State: APjAAAVosQD7g9H8l1d7UxGW3idgwdGpt6HCvnweekjmrRDz77fzJATV 3+/gNrdU/kc0rCL9EvTc2J/jFA== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id t22sm416199otq.18.2020.02.10.11.31.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); 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 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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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: 11373993 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 3D73A1820 for ; Mon, 10 Feb 2020 19:31:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1595A2173E for ; Mon, 10 Feb 2020 19:31:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="kD5EGiWm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727779AbgBJTbG (ORCPT ); Mon, 10 Feb 2020 14:31:06 -0500 Received: from mail-ot1-f65.google.com ([209.85.210.65]:33971 "EHLO mail-ot1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727752AbgBJTbF (ORCPT ); Mon, 10 Feb 2020 14:31:05 -0500 Received: by mail-ot1-f65.google.com with SMTP id a15so7598577otf.1 for ; Mon, 10 Feb 2020 11:31:04 -0800 (PST) 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=j0XDVbd3hOsMH8hCbNK3Ab2v+4gh4PA49vBy8ozdBwf6eMaUK+qzUICYFvEEshr/lc IJWrVp4R1igFqHI0zj/VtBU/vayAiZukWFF+U1pca+O/W9IGwn65XGLhCw6xtGM+InLe aQGR3wlPzK698+wHMtdOQRH5nNyV/ln4RQEtuj4kNeQ6KDBfXuV8pDcqWkMBI7EBUIFG YjZPx6DV7KKs1dX6Rgqmw7jKgGXC4wGcnrS0dqtbI1lFXLceaAVo921qLEjJ8jStP/ii RA1if3LD+1bcYFQF4FhgUNhrAlioNISTO9otOv7FkNcad9IWL/CGHd2GVe2nx9i6JGEG X0RQ== X-Gm-Message-State: APjAAAWZDo1cOcNhE586q6wUlUNZgbz3XQQ/zFV6i+1m8Mr810fHBb5h okz2ATgtCkZGlo9t6NcIinIkiQ== 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) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id p24sm358258otq.64.2020.02.10.11.31.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2020 11:31:02 -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 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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; +}