From patchwork Wed Feb 14 12:28:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 13556404 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 6BCC6C48BC1 for ; Wed, 14 Feb 2024 12:30:02 +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:Cc:To:From:Subject:Message-ID: References:Mime-Version:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=lqn9+cUFvYRTJyQwxG/rDP055ei9W69+nuzucXwDrJo=; b=WQ64ThP9VstlQhYb2XaRsDm+6G m+OtnLB/u5Z0+kg2r3e25+QHwYiykFfK6WE5fz0iO1pVwbRMMvhh5lf+LI1Y0BZbs8EEAp3w4Ww2q 0yzBoAc8F4A/qRAi50lfrZyjkuDwn/bAard0SU9+Nv1l1T3eMI8uGdkrrNK2r+YScQL2z4Pi8idUs pKzHAEuqEj7JQ6x2Rhft0/Mz5BKyEuha4x16aMfWu80MLxNjupcwCHqa0/V4l+2x4F5zemqzrI8MX G1syCDeKuiRypfpiPw3tqXIx1rZ8kcE6g6mZma/+bJKbKXz+pobCGlShaqJU5ybGcvad8UlS8/3of vfKkNbJQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1raEOe-0000000CoGL-1AAG; Wed, 14 Feb 2024 12:29:52 +0000 Received: from mail-wm1-x34a.google.com ([2a00:1450:4864:20::34a]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1raEOY-0000000CoDc-0IUT for linux-arm-kernel@lists.infradead.org; Wed, 14 Feb 2024 12:29:47 +0000 Received: by mail-wm1-x34a.google.com with SMTP id 5b1f17b1804b1-410dfd0e1caso17539705e9.0 for ; Wed, 14 Feb 2024 04:29:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707913781; x=1708518581; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=E7ySR0vcU7U/Aj19kq5Li5vJqxJ6gFKIuAubeInPysA=; b=m8yR01nHEZOEe3w2n0e/s0jNeJUgLOXIM/F/8QzGzXmyE8gb6CdOxpz57+YaM8+ff9 CeChn3qHLGuH32It9uURx+gSkjpLyZ1GFGeC3iQXfdGm5F0B4dVKOsiiS3FQjwSeoHNj UazxgdCmYqt4SaLctU/vGfWZ7jLqrj4z0d5Jok4LMc3o5/UzmQz/ywxPaMl5IxEXP7Yv wDEhlRW9Vlaoh/4e0b26Zheb5jlHvoTU5wfEj69Qcz3vnWcrNpiNucY7siLRwMdobC+m JQ08tMRqX861DpybpK/kzmL7eebNrOZJYpVd0Oqu4kxrEItOBMeoJbBnnDo0qxe9sRDV dXzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707913781; x=1708518581; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=E7ySR0vcU7U/Aj19kq5Li5vJqxJ6gFKIuAubeInPysA=; b=oesE2Wk3c5k6V3l3bxhbaQu6U7z3jPEf/2gQw4ASlKaxLoFFT3AQKNfaAIFY5ih6Nb uhaRZlO/oDijbzpi3z7ZJYQo/YtFD1Dv3bZNVPIZcD8TBYeoLhJi7SIeVTXZc23VJnca CWrA790eG027bNuzoJ5X1AYdndDkdy4eQfISD9vi9lQY6I6tRj0O2sJfODVoBMRAqegv Pp3XzvwDP3yk29uCjBHgJr08K4hyMsNtn+kp/5FxIIH2WFfJZlQ7n4aiG0TeNypBqvog 4FRY40UpZR6HjEHsrLkAaeUxN8nHSiU/9sc8yTrB3S9PNarzkj5aVRWAZ3sYimWyaYFP qDjw== X-Gm-Message-State: AOJu0YyFJu6nVZmZiOYVGLVTbsvs25927cQQis7/djPQ2QrS1+S219zl 3k6PqaRfCKye8DHvHfZxWh1176uT7t+CSaC2MqxV/FMQMAPA6+trQ7jep7SD7lbIWhyUzV8tdSI RZABI+MYQtOkl/qkkQgw/6/53NZA0BfqtxjWG1UbsKkr2tuNHMcprRuF5J6u6MLUyJ6S+S/4vOj pkSKUEFukHfcmHWXQ7qVjCnunZ7nTp2vB6xKccBkt/ X-Google-Smtp-Source: AGHT+IFoQaUzd1JgkYf56DM1ovETFXcNoqK4k6Atizk1cbAgOh5ZrtumDFegxS65tsOSmS9SAKNPctZS X-Received: from palermo.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:118a]) (user=ardb job=sendgmr) by 2002:a05:600c:54e8:b0:40f:dfef:cd4 with SMTP id jb8-20020a05600c54e800b0040fdfef0cd4mr42680wmb.6.1707913781213; Wed, 14 Feb 2024 04:29:41 -0800 (PST) Date: Wed, 14 Feb 2024 13:28:47 +0100 In-Reply-To: <20240214122845.2033971-45-ardb+git@google.com> Mime-Version: 1.0 References: <20240214122845.2033971-45-ardb+git@google.com> X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=6618; i=ardb@kernel.org; h=from:subject; bh=qltVUJ0baJKnUmgvQnZvF+l5dl5tPI+hJ6wQoQcDNqs=; b=owGbwMvMwCFmkMcZplerG8N4Wi2JIfXMxv9l23yaP7Y45KbOEF1lcaaiKGKz12SROXOKz63Q5 8w6ULGqo5SFQYyDQVZMkUVg9t93O09PlKp1niULM4eVCWQIAxenAEwkrImR4XiSx64jRYEOpgwL 4r9MYy/4YHZUXNyCVdl+ou26e9tzxRkZTjGeWim9OKH41neNZq0m6xtHb5nNuX1HdNnDkFWfebs fMAIA X-Mailer: git-send-email 2.43.0.687.g38aa6559b0-goog Message-ID: <20240214122845.2033971-46-ardb+git@google.com> Subject: [PATCH v8 01/43] arm64: kernel: Manage absolute relocations in code built under pi/ From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: Ard Biesheuvel , Catalin Marinas , Will Deacon , Marc Zyngier , Mark Rutland , Ryan Roberts , Anshuman Khandual , Kees Cook X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240214_042946_145686_7C34CC23 X-CRM114-Status: GOOD ( 24.13 ) 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 From: Ard Biesheuvel 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, identifying the ones 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 sections) and will never occur in compiler generated code sections when using the small code model, so only check sections that have SHF_ALLOC set and SHF_EXECINSTR cleared. To accommodate cases where statically initialized symbol references are unavoidable, introduce a special case for ELF input data sections that have ".rodata.prel64" in their names, and in these cases, instead of rejecting any encountered ABS64 relocations, convert them into PREL64 relocations, which don't require any runtime fixups. Note that the code in question must still be modified to deal with this, as it needs to convert the 64-bit signed offsets into absolute addresses before use. Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/pi/Makefile | 9 +- arch/arm64/kernel/pi/pi.h | 18 +++ arch/arm64/kernel/pi/relacheck.c | 130 ++++++++++++++++++++ 3 files changed, 155 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/pi/Makefile b/arch/arm64/kernel/pi/Makefile index c844a0546d7f..bc32a431fe35 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 = $(cmd_objcopy) && $(obj)/relacheck $(@) $(<) + $(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/pi.h b/arch/arm64/kernel/pi/pi.h new file mode 100644 index 000000000000..7c2d9bbf0ff9 --- /dev/null +++ b/arch/arm64/kernel/pi/pi.h @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright 2023 Google LLC +// Author: Ard Biesheuvel + +#define __prel64_initconst __section(".init.rodata.prel64") + +#define PREL64(type, name) union { type *name; prel64_t name ## _prel; } + +#define prel64_pointer(__d) (typeof(__d))prel64_to_pointer(&__d##_prel) + +typedef volatile signed long prel64_t; + +static inline void *prel64_to_pointer(const prel64_t *offset) +{ + if (!*offset) + return NULL; + return (void *)offset + *offset; +} diff --git a/arch/arm64/kernel/pi/relacheck.c b/arch/arm64/kernel/pi/relacheck.c new file mode 100644 index 000000000000..b0cd4d0d275b --- /dev/null +++ b/arch/arm64/kernel/pi/relacheck.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 - 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 Elf64_Ehdr *ehdr; +static Elf64_Shdr *shdr; +static const char *strtab; +static bool swap; + +static uint64_t swab_elfxword(uint64_t val) +{ + return swap ? __builtin_bswap64(val) : val; +} + +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 < 3) { + fprintf(stderr, "file arguments 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 | PROT_WRITE, MAP_SHARED, 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); + strtab = (void *)ehdr + + swab_elfxword(shdr[swab_elfhword(ehdr->e_shstrndx)].sh_offset); + + for (int i = 0; i < swab_elfhword(ehdr->e_shnum); i++) { + unsigned long info, flags; + bool prel64 = false; + 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; + + /* + * We generally don't permit ABS64 relocations in the code that + * runs before relocation processing occurs. If statically + * initialized absolute symbol references are unavoidable, they + * may be emitted into a *.rodata.prel64 section and they will + * be converted to place-relative 64-bit references. This + * requires special handling in the referring code. + */ + if (strstr(strtab + swab_elfword(shdr[info].sh_name), + ".rodata.prel64")) { + prel64 = true; + } + + 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) + continue; + + if (prel64) { + /* convert ABS64 into PREL64 */ + info ^= R_AARCH64_ABS64 ^ R_AARCH64_PREL64; + rela[j].r_info = swab_elfxword(info); + } else { + fprintf(stderr, + "Unexpected absolute relocations detected in %s\n", + argv[2]); + close(fd); + unlink(argv[1]); + exit(EXIT_FAILURE); + } + } + } + close(fd); + return 0; +}