From patchwork Fri Nov 11 17:11:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 13040626 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DCABBC4332F for ; Fri, 11 Nov 2022 17:16:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=CtlkyVy0/B7uLY0H0qdwLlf7Go/W2y7qqeHTfHh8t6Y=; b=lZfIqTYXyRQaz4 xMVsTvROwfyywpTY08NILBJ4bBLnK8dP1Pigh4JxdJos/0brULP8oYdnJHLV7PuSCbQncUj6oweoB gpKVDD/dAyFY0RX29PVn0bqiLRtHt85dZu2aA3/wZbcJctcy+gANZo/VG0OX3bPFP+UUgBDXbvIWp pPvjdlbx2qvkPwybtteQ8hAoLAvSjPGpNz1L5UMdTNdimIt4x6hAn1vqOEkt9QqaVs1i2FJ0PI46q +TUA4nWlx6gzUk6iIBm1teMPk2op8Zj3UVt/WkfVIlAWOhZonzTpawW1XCeNDFPrV6Zu/LJiWdbdG kHO4tb9pHOzTmtE0wv/A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1otXcb-00H91m-Dd; Fri, 11 Nov 2022 17:15:17 +0000 Received: from ams.source.kernel.org ([145.40.68.75]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1otXZy-00H7aX-VE for linux-arm-kernel@lists.infradead.org; Fri, 11 Nov 2022 17:12:36 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 98B4DB8267B; Fri, 11 Nov 2022 17:12:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6546BC43144; Fri, 11 Nov 2022 17:12:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1668186752; bh=2jU7X7NRPByZdbNZ3bzi7gLzJ6OfyCcumL153oY3F70=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RgfwcoOF4taEQI2BJ1fINBYidYjB/mhuhOfB1lNxrY7nn8i/WCD87XVbOjVvRobaX OQG6zgzRJ3aI332TxRXhdZD+QZ23DHUXCm2dqbjIJK8kYX+q+toqypHwX45duP7ZoK 9XGGC458kmJbbXXuGYEBkvdebMbeAl850aNqR4p8Pirti1WWw0F41WzAq0L1sZKkXE uAD3PC9z0YXt3/yqezhWHCR+0HoMAgtQDxSIkRHd8hUsLRR8zIGxwj4Nz+e+X/T9NY 2J+8ZqV05CsH6qfMOtT1j79KYl+TzEP7l25+tReyaCATiQeVWcHnY0gBNFiCKyp/3D P7WlY1B1Rpd2w== From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: Ard Biesheuvel , Marc Zyngier , Will Deacon , Mark Rutland , Kees Cook , Catalin Marinas , Mark Brown , Anshuman Khandual Subject: [PATCH v7 06/33] arm64: kernel: Add relocation check to code built under pi/ Date: Fri, 11 Nov 2022 18:11:34 +0100 Message-Id: <20221111171201.2088501-7-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221111171201.2088501-1-ardb@kernel.org> References: <20221111171201.2088501-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4367; i=ardb@kernel.org; h=from:subject; bh=2jU7X7NRPByZdbNZ3bzi7gLzJ6OfyCcumL153oY3F70=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjboIyMJnk4unNMOMK4fmGHAm3Zl3TOjD+rLjxKdW5 hidCPc2JAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCY26CMgAKCRDDTyI5ktmPJFYEDA CKFf9730UNrMceTDaML8/kCqML3ZKk3733fljheQrZBQlQjvsn4xYXy46mhSmLUaAKU9PjRjC+dnd3 2vduRIhL5Ne5ZJE45Oy/39uZsM+k7LLTbcEpCVbN10/NzXrhJy5Pe8xEd/tU6loqhN89rQIdsWOR5X Ox3VcmGRK/zJ4/VTRcZM2ryhCRWW7p9hyHJiTm+t8F6pYz0Amh3WD1q/pQa0SaJzmW9AOY64Dn4jM3 bAjIdRvAMmydQhH0VzmBzfxRZv+0xhZM8ZNM/EjmK7zLUkDN+xILhPvSLDSmX3q791Llpyv15NkhFW jY4nWDlbz7wWK1pdmKFjzVDeV01cVbE7BHyVWhl0/BffY4/vt3d3XQcE/C0yLo8X7YrR0ELFVtp9+B ujsLRDDatowwzpsf8dhmUlZp+M7biFIvVGY6Bcyld604Tx00nzVFhrOf9WgQdMDWODrYhh+s07TJ3R nG5UarV5DvDF1w9pN43zzyrLGB6PPjWFPsxOkT+3XvW3A= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221111_091235_352041_8DC1A879 X-CRM114-Status: GOOD ( 20.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The mini C runtime runs before relocations are processed, and so it cannot rely on statically initialized pointer variables. Add a check to ensure that such code does not get introduced by accident, by going over the relocations in each object that operate on data sections that are part of the executable image, and raising an error if any relocations of type R_AARCH64_ABS64 exist. Note that such relocations are permitted in other places (e.g., debug section) and can never occur in compiler generated code sections, so only check sections that have SHF_ALLOC set and SHF_EXECINSTR cleared. Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/pi/Makefile | 9 +- arch/arm64/kernel/pi/relacheck.c | 104 ++++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/pi/Makefile b/arch/arm64/kernel/pi/Makefile index c844a0546d7f0e62..810fdae897601e88 100644 --- a/arch/arm64/kernel/pi/Makefile +++ b/arch/arm64/kernel/pi/Makefile @@ -22,11 +22,16 @@ KCSAN_SANITIZE := n UBSAN_SANITIZE := n KCOV_INSTRUMENT := n +hostprogs := relacheck + +quiet_cmd_piobjcopy = $(quiet_cmd_objcopy) + cmd_piobjcopy = $(obj)/relacheck $< && $(cmd_objcopy) + $(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_ \ --remove-section=.note.gnu.property \ --prefix-alloc-sections=.init -$(obj)/%.pi.o: $(obj)/%.o FORCE - $(call if_changed,objcopy) +$(obj)/%.pi.o: $(obj)/%.o $(obj)/relacheck FORCE + $(call if_changed,piobjcopy) $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) diff --git a/arch/arm64/kernel/pi/relacheck.c b/arch/arm64/kernel/pi/relacheck.c new file mode 100644 index 0000000000000000..1039259360c735d2 --- /dev/null +++ b/arch/arm64/kernel/pi/relacheck.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 - Google LLC + * Author: Ard Biesheuvel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define HOST_ORDER ELFDATA2LSB +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define HOST_ORDER ELFDATA2MSB +#endif + +static bool swap; + +static uint64_t swab_elfxword(uint64_t val) +{ + return swap ? __builtin_bswap64(val) : val; +} + +static Elf64_Ehdr *ehdr; +static Elf64_Shdr *shdr; + +static uint32_t swab_elfword(uint32_t val) +{ + return swap ? __builtin_bswap32(val) : val; +} + +static uint16_t swab_elfhword(uint16_t val) +{ + return swap ? __builtin_bswap16(val) : val; +} + +int main(int argc, char *argv[]) +{ + struct stat stat; + int fd, ret; + + if (argc < 2) { + fprintf(stderr, "file argument missing\n"); + exit(EXIT_FAILURE); + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) { + fprintf(stderr, "failed to open %s\n", argv[1]); + exit(EXIT_FAILURE); + } + + ret = fstat(fd, &stat); + if (ret < 0) { + fprintf(stderr, "failed to stat() %s\n", argv[1]); + exit(EXIT_FAILURE); + } + + ehdr = mmap(0, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (ehdr == MAP_FAILED) { + fprintf(stderr, "failed to mmap() %s\n", argv[1]); + exit(EXIT_FAILURE); + } + + swap = ehdr->e_ident[EI_DATA] != HOST_ORDER; + shdr = (void *)ehdr + swab_elfxword(ehdr->e_shoff); + + for (int i = 0; i < swab_elfhword(ehdr->e_shnum); i++) { + unsigned long info, flags; + const Elf64_Rela *rela; + int numrela; + + if (swab_elfword(shdr[i].sh_type) != SHT_RELA) + continue; + + /* only consider RELA sections operating on data */ + info = swab_elfword(shdr[i].sh_info); + flags = swab_elfxword(shdr[info].sh_flags); + if ((flags & (SHF_ALLOC | SHF_EXECINSTR)) != SHF_ALLOC) + continue; + + rela = (void *)ehdr + swab_elfxword(shdr[i].sh_offset); + numrela = swab_elfxword(shdr[i].sh_size) / sizeof(*rela); + + for (int j = 0; j < numrela; j++) { + uint64_t info = swab_elfxword(rela[j].r_info); + + if (ELF64_R_TYPE(info) == R_AARCH64_ABS64) { + fprintf(stderr, + "Absolute relocations detected in %s\n", + argv[1]); + exit(EXIT_FAILURE); + } + } + } + return 0; +}