From patchwork Fri Oct 18 17:25:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 176916 Delivered-To: patch@linaro.org Received: by 2002:a92:7e96:0:0:0:0:0 with SMTP id q22csp1160877ill; Fri, 18 Oct 2019 10:28:05 -0700 (PDT) X-Google-Smtp-Source: APXvYqwsQZk5Ra5LNli6lOGekLlnkxcY+OFo7Kof/q6hT+W5EQ910Bi1lHAr2RpCmbcX4Hzosntq X-Received: by 2002:a05:6402:751:: with SMTP id p17mr10912219edy.161.1571419685165; Fri, 18 Oct 2019 10:28:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571419685; cv=none; d=google.com; s=arc-20160816; b=XKylNH79PKZcsyy5w/xbvZe+WC5Epm/2+/etFnYUrMBjavq6e62Sb5jUPN5GPUFS0Z JAQV69Rg8uXtXYjXzyxqm7Udb/rcKW6cAtf7laWML5Y0Yh3bHxxpXbPpjKlP4+i69HNy PGcDu6ukCfXSJDWdc3SeG93h+CNNK8k0DFgcZFY0v8j/Lx+Bz6XNrG9L5yX1ACwJRWu+ wR0PB9STR5h+pmIo5j3k/t+Mnf3ljtzoVgBIrS8958ERAQnWUfoKBxvX5yBeVGdkYwnq q9oK9mhz2OQd0dyUfSjBDoEBTKCmnAgsakOy7+4jjmiBesdLQSUC7hwURRHZwGGg7Aud zSyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=tBhum6fp2rmS0czvTIdbJEGOCKSOmViV92hel5wyTjs=; b=03fyB61RB2Pl5SjVdNgenK8mh4kN3R+pJin8XpLkzFdRQIaAuF8XlMzPdgdPCnl/Jf 2syQdGDXr6Vv1UNEXOD2ZKeRtKB+pUTEI2JSUmTAhxSVCgC2Zkjbf8FQBqaSHoT9PdlA onxufi2aGnHv8DN7tzYUkz1VenO6LYs9Q1l1Rt6xR8IwVgnQtTIY+mT2YB+75dt8F8bJ E+sqWGM8LZWrtei+t6tKnL3uizzK4UV6um13lsOHP+ypj0ltJVn4KpVn9QOS7IYmc6Oh yfKsnMqNuHTog4IQex5fY2PjYPtrnJKge6XAwrPKkpLHCdnGGBRoSYDCe1T9WZTciGJO zL6g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l9si3580036ejq.164.2019.10.18.10.28.04; Fri, 18 Oct 2019 10:28:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2505556AbfJRR2C (ORCPT + 26 others); Fri, 18 Oct 2019 13:28:02 -0400 Received: from [217.140.110.172] ([217.140.110.172]:47138 "EHLO foss.arm.com" rhost-flags-FAIL-FAIL-OK-OK) by vger.kernel.org with ESMTP id S2502095AbfJRR1Z (ORCPT ); Fri, 18 Oct 2019 13:27:25 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 69BAB1435; Fri, 18 Oct 2019 10:26:56 -0700 (PDT) Received: from e103592.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 81BAD3F718; Fri, 18 Oct 2019 10:26:53 -0700 (PDT) From: Dave Martin To: linux-kernel@vger.kernel.org Cc: Andrew Jones , Arnd Bergmann , Catalin Marinas , Eugene Syromiatnikov , Florian Weimer , "H.J. Lu" , Jann Horn , Kees Cook , =?utf-8?q?Kristina_Mart=C5=A1enko?= , Marc Zyngier , Mark Brown , Paul Elliott , Peter Zijlstra , Richard Henderson , Sudakshina Das , Szabolcs Nagy , Thomas Gleixner , Will Deacon , Yu-cheng Yu , Amit Kachhap , Vincenzo Frascino , linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v3 07/12] arm64: elf: Enable BTI at exec based on ELF program properties Date: Fri, 18 Oct 2019 18:25:40 +0100 Message-Id: <1571419545-20401-8-git-send-email-Dave.Martin@arm.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1571419545-20401-1-git-send-email-Dave.Martin@arm.com> References: <1571419545-20401-1-git-send-email-Dave.Martin@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org For BTI protection to be as comprehensive as possible, it is desirable to have BTI enabled from process startup. If this is not done, the process must use mprotect() to enable BTI for each of its executable mappings, but this is painful to do in the libc startup code. It's simpler and more sound to have the kernel do it instead. To this end, detect BTI support in the executable (or ELF interpreter, as appropriate), via the NT_GNU_PROGRAM_PROPERTY_TYPE_0 note, and tweak the initial prot flags for the process' executable pages to include PROT_BTI as appropriate. Signed-off-by: Dave Martin --- arch/arm64/Kconfig | 3 +++ arch/arm64/include/asm/elf.h | 50 ++++++++++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/process.c | 19 +++++++++++++++++ include/linux/elf.h | 6 +++++- include/uapi/linux/elf.h | 6 ++++++ 5 files changed, 83 insertions(+), 1 deletion(-) -- 2.1.4 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index bb3189e..a64d91d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -9,6 +9,7 @@ config ARM64 select ACPI_MCFG if (ACPI && PCI) select ACPI_SPCR_TABLE if ACPI select ACPI_PPTT if ACPI + select ARCH_BINFMT_ELF_STATE select ARCH_CLOCKSOURCE_DATA select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEVMEM_IS_ALLOWED @@ -34,6 +35,7 @@ config ARM64 select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_TEARDOWN_DMA_OPS if IOMMU_SUPPORT select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST + select ARCH_HAVE_ELF_PROT select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_INLINE_READ_LOCK if !PREEMPT select ARCH_INLINE_READ_LOCK_BH if !PREEMPT @@ -63,6 +65,7 @@ config ARM64 select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPT select ARCH_KEEP_MEMBLOCK select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_USE_GNU_PROPERTY if BINFMT_ELF select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS select ARCH_SUPPORTS_MEMORY_FAILURE diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index b618017..8bc154c 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -114,7 +114,11 @@ #ifndef __ASSEMBLY__ +#include #include +#include +#include +#include #include /* for signal_minsigstksz, used by ARCH_DLINFO */ typedef unsigned long elf_greg_t; @@ -224,6 +228,52 @@ extern int aarch32_setup_additional_pages(struct linux_binprm *bprm, #endif /* CONFIG_COMPAT */ +struct arch_elf_state { + int flags; +}; + +#define ARM64_ELF_BTI (1 << 0) + +#define INIT_ARCH_ELF_STATE { \ + .flags = 0, \ +} + +static inline int arch_parse_elf_property(u32 type, const void *data, + size_t datasz, bool compat, + struct arch_elf_state *arch) +{ + /* No known properties for AArch32 yet */ + if (IS_ENABLED(CONFIG_COMPAT) && compat) + return 0; + + if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { + const u32 *p = data; + + if (datasz != sizeof(*p)) + return -EIO; + + if (IS_ENABLED(CONFIG_ARM64_BTI) && + (*p & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) + arch->flags |= ARM64_ELF_BTI; + } + + return 0; +} + +static inline int arch_elf_pt_proc(void *ehdr, void *phdr, + struct file *f, bool is_interp, + struct arch_elf_state *state) +{ + return 0; +} + +static inline int arch_check_elf(void *ehdr, bool has_interp, + void *interp_ehdr, + struct arch_elf_state *state) +{ + return 0; +} + #endif /* !__ASSEMBLY__ */ #endif diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index a47462d..4c78937 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -11,12 +11,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -633,3 +635,20 @@ static int __init tagged_addr_init(void) core_initcall(tagged_addr_init); #endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */ + +#ifdef CONFIG_BINFMT_ELF +int arch_elf_adjust_prot(int prot, const struct arch_elf_state *state, + bool has_interp, bool is_interp) +{ + if (is_interp != has_interp) + return prot; + + if (!(state->flags & ARM64_ELF_BTI)) + return prot; + + if (prot & PROT_EXEC) + prot |= PROT_BTI; + + return prot; +} +#endif diff --git a/include/linux/elf.h b/include/linux/elf.h index 1b6e895..5d5b032 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -63,7 +63,11 @@ extern int elf_coredump_extra_notes_size(void); extern int elf_coredump_extra_notes_write(struct coredump_params *cprm); #endif -/* NT_GNU_PROPERTY_TYPE_0 header */ +/* + * NT_GNU_PROPERTY_TYPE_0 header: + * Keep this internal until/unless there is an agreed UAPI definition. + * pr_type values (GNU_PROPERTY_*) are public and defined in the UAPI header. + */ struct gnu_property { u32 pr_type; u32 pr_datasz; diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 20900f4..c6dd021 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -448,4 +448,10 @@ typedef struct elf64_note { Elf64_Word n_type; /* Content type */ } Elf64_Nhdr; +/* .note.gnu.property types for EM_AARCH64: */ +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 + +/* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) + #endif /* _UAPI_LINUX_ELF_H */