From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53E6E49504E for ; Wed, 7 Oct 2026 11:43:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.197 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791373455; cv=none; b=YvP7Tv19ZJPOATa9V1xn3HWuKWj6tutkAylV/P9RYQQOwtrwubkz4s+tQhePvgF/YC0h3qp9ESG+GzfSZviboDECWgtrS96m+4g+SGng3mEuauLpLeL3wK4QU3OSd3pHoIsCI565rWYEdCFYU8CEFVvdMxClHg0HmC6mWJIyEmc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791373455; c=relaxed/simple; bh=AymkOFYhpuoaYlczb6jgOItl+WSRrFMCpchS7hx5hZE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GY//gBKzivs6PveGRQewTTcMZFaWca4RJ1mr5dxdbC9D3cQ0KJuiCaF0an7/710cpixv09vM80XC7A4xOmNYe7Jda+NUy1V+Ldvwg14RAxwuYSSIoXpMIyiQ2KvhqQFewwwCyASRceC/9Elw6+wkzY51N314cGaQiEXjhE7W86w= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dylanbhatch.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=iTN9AwN+; arc=none smtp.client-ip=209.85.214.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dylanbhatch.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="iTN9AwN+" Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-2d02df2bf09so33235175ad.0 for ; Wed, 07 Oct 2026 04:43:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1791373437; x=1791978237; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=fgc8jaasabhbUwfJLQvrAFQRGkLXxRtpOJ5ukzG0TY4=; b=iTN9AwN+M0FYprp9JToqDwwZTjUWBYLpcMPDNMczEgjLCwydKX+QKcBjKx7IFcSWI2 5QQAzdJaJcYFeTbr01EJrOS8ufrrO+uPhD62RkoT/ZSNBQwCdzuPgC7eHt3uehgRl473 ZBNSTNmXoyBWMQeQeekjfsNluDiOynEXnzVKSMUvzVAYZnI5DOu4GUXedUGeK/RvrhoO TOQ52tlDwST9dNaAAUmyrq9gEyba5uBBJIL2nux40ppkIRFQg1xvrFQQiqreylcnLEr0 j2yBUEgpURt8Y1gqZDZVaxbpb1H2brdNtRyjaLxtgorXNp/phl7z/myJUA9NKZdKfrId 1P0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791373437; x=1791978237; h=content-type: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:content-type; bh=fgc8jaasabhbUwfJLQvrAFQRGkLXxRtpOJ5ukzG0TY4=; b=s7NYZQPvWD1tAbTskC4sTNL4P819r0yke2YpcrTffQPbvYIhuaJ/4g+FXZJbhDHxfb IAhsHRF2363dYyehKXZ6SATDf2/6opvTQw9G3YuuPA7SnCWOooAO3DEmb94w6mcDYYZg KrhpNFjqoDfdCx2BX1LJ1WjMn/BMG2cEAyS/vKcVUCtkitN69DR8cVdGxXoo03RwXEMC 5qErqyfQ/995sxsoloHTMZD1ra7XSq3XgJga/YShBIiOZD/0LHB5uCSA1/InoWYCpWdL n+6sTXOWMuDEPfXN3kjjtu9wrP0i/DnjoydVowU0VbCaY3qUJi6wWWJJ00nqR9gJzmFy UzWw== X-Forwarded-Encrypted: i=1; AKwUvBxWiIBRCXJjUylT58sxcLCPc1j4kFNaHjp7uf5LeNg+6lI++fLMNKmP2jwB7qgnAtMoVBUSYi3pKKLRH4U=@vger.kernel.org X-Gm-Message-State: AFq9FYLmQL7yc4lSwrbsElD6j1VSVT4Yr48PR3deHTFd1DWZaLp58dZt 3/aIwpTtTG3LBR16No23OeLF3NuyLwyxl2aDZ/By5/xJRCTE1xCVMgoV2/bCkZAudYdKQ/T89R/ vGrg3snNKCwRE15fpDfwN7OAC8A== X-Received: from ploh5.prod.google.com ([2002:a17:902:f705:b0:2e6:14d:bd91]) (user=dylanbhatch job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:4b24:b0:2dd:c0ff:e72e with SMTP id d9443c01a7336-2e60054be54mr15589775ad.64.1791373437250; Wed, 07 Oct 2026 04:43:57 -0700 (PDT) Date: Wed, 7 Oct 2026 11:43:30 +0000 In-Reply-To: <20261007114335.440322-1-dylanbhatch@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20261007114335.440322-1-dylanbhatch@google.com> X-Mailer: git-send-email 2.56.0.360.g66cac248cb-goog Message-ID: <20261007114335.440322-7-dylanbhatch@google.com> Subject: [PATCH v8 06/11] arm64/sframe: Validate IP addresses From: Dylan Hatch To: Roman Gushchin , Weinan Liu , Will Deacon , Josh Poimboeuf , Indu Bhagat , Peter Zijlstra , Steven Rostedt , Catalin Marinas , Jiri Kosina , Mark Rutland , Jens Remus Cc: Dylan Hatch , Prasanna Kumar T S M , Puranjay Mohan , Song Liu , joe.lawrence@redhat.com, linux-toolchains@vger.kernel.org, linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Randy Dunlap , Mostafa Saleh , Herbert Xu , "David S. Miller" Content-Type: text/plain; charset="UTF-8" Validate the given IP and computed function start address against the known vmlinux and module text address ranges. This requires arch-specific validation for vmlinux. This is because arm64 keeps .exit.text (normally discarded) and .rodata.text, both of both of which lie outside the bounds of .text and .init.text. Note that .rodata.text contains code that is never executed by the kernel mapping, but for which the toolchain nonetheless generates sframe data, and needs to be considered valid at lookup time. Suggested-by: Jens Remus Signed-off-by: Dylan Hatch --- Changes since v7: - (sashiko) Use __always_inline for IP validation helper. --- arch/arm64/include/asm/sections.h | 1 + arch/arm64/include/asm/unwind_sframe.h | 32 +++++++++++++++++++ arch/arm64/kernel/vmlinux.lds.S | 2 ++ kernel/unwind/sframe.c | 43 +++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/include/asm/unwind_sframe.h diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h index 51b0d594239eb..5edb4304f661e 100644 --- a/arch/arm64/include/asm/sections.h +++ b/arch/arm64/include/asm/sections.h @@ -23,6 +23,7 @@ extern char __irqentry_text_start[], __irqentry_text_end[]; extern char __mmuoff_data_start[], __mmuoff_data_end[]; extern char __entry_tramp_text_start[], __entry_tramp_text_end[]; extern char __relocate_new_kernel_start[], __relocate_new_kernel_end[]; +extern char _srodatatext[], _erodatatext[]; static inline size_t entry_tramp_text_size(void) { diff --git a/arch/arm64/include/asm/unwind_sframe.h b/arch/arm64/include/asm/unwind_sframe.h new file mode 100644 index 0000000000000..1b45d328c746f --- /dev/null +++ b/arch/arm64/include/asm/unwind_sframe.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_ARM64_UNWIND_SFRAME_H +#define _ASM_ARM64_UNWIND_SFRAME_H + +#include +#include +#include + +static __always_inline bool sframe_is_kernel_ip_valid(unsigned long ip) +{ + if (__is_kernel_text(ip) || is_kernel_inittext(ip)) + return true; + + /* .exit.text is retained in vmlinux on arm64. */ + if (ip >= (unsigned long)__exittext_begin && + ip < (unsigned long)__exittext_end) + return true; + + /* + * .rodata.text is never executed from the kernel mapping, but it still + * has sframe data. + */ + if (ip >= (unsigned long)_srodatatext && + ip < (unsigned long)_erodatatext) + return true; + + return false; +} + +#define sframe_is_kernel_ip_valid sframe_is_kernel_ip_valid + +#endif /* _ASM_ARM64_UNWIND_SFRAME_H */ diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index eb1f54829503c..82fd20ccb7c43 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -237,12 +237,14 @@ SECTIONS /* code sections that are never executed via the kernel mapping */ .rodata.text : { + _srodatatext = .; TRAMP_TEXT HIBERNATE_TEXT KEXEC_TEXT IDMAP_TEXT . = ALIGN(PAGE_SIZE); } + _erodatatext = .; idmap_pg_dir = .; . += PAGE_SIZE; diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 33883408581da..c95fcb63e7eaf 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -44,6 +44,45 @@ struct sframe_fre_internal { unsigned char dw_size; }; +#ifndef sframe_is_kernel_ip_valid + +static __always_inline bool sframe_is_kernel_ip_valid(unsigned long ip) +{ + return __is_kernel_text(ip) || is_kernel_inittext(ip); +} + +#endif + +#ifdef CONFIG_MODULES + +static __always_inline bool sframe_is_sec_module_ip_valid(struct sframe_section *sec, + unsigned long ip) +{ + struct module *mod = container_of(sec, struct module, sframe_sec); + + return within_module_mem_type(ip, mod, MOD_TEXT) || + within_module_mem_type(ip, mod, MOD_INIT_TEXT); +} + +#else + +static __always_inline bool sframe_is_sec_module_ip_valid(struct sframe_section *sec, + unsigned long ip) +{ + return false; +} + +#endif + +static __always_inline bool is_sec_ip_valid(struct sframe_section *sec, + unsigned long ip) +{ + if (sec == &kernel_sfsec) + return sframe_is_kernel_ip_valid(ip); + + return sframe_is_sec_module_ip_valid(sec, ip); +} + static __always_inline unsigned char fre_type_to_size(unsigned char fre_type) { if (fre_type > 2) @@ -70,6 +109,8 @@ static __always_inline int __read_fde(struct sframe_section *sec, _fde = (struct sframe_fde_v3 *)fde_addr; func_addr = fde_addr + _fde->func_start_off; + if (!is_sec_ip_valid(sec, func_addr)) + return -EINVAL; fda_addr = sec->fres_start + _fde->fres_off; if (fda_addr + sizeof(struct sframe_fda_v3) > sec->fres_end || @@ -450,7 +491,7 @@ noinstr int sframe_find(unsigned long ip, struct unwind_frame *frame) if (!frame) return -EINVAL; - if (__is_kernel_text(ip) || is_kernel_inittext(ip)) { + if (sframe_is_kernel_ip_valid(ip)) { if (!sframe_init) return -EINVAL; -- 2.56.0.360.g66cac248cb-goog