From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D911E20F062; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940718; cv=none; b=tT2s/swZBbifPPF9GcSb2BUl1XPZIHi7aoK/dbPjs3dxxK5unZmmJ3QIIy1fT1cyS43kS8Ahynv4MFiG2lvr9Xs0nOq2H3BFKwjqv+XPxV8fnbhAQRe8Yf4CyCeOzs74SmAf72nkbLfTzjFZ3w909rfmgNLRhZP3OR13M59QilI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940718; c=relaxed/simple; bh=Jwf3IJv5L+/CRPGF2QZQl1YIeSHddJV1V5U7FHvFfQI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=B4dVbIzk8TuhiZvJA1XmJdDm046kUHYwdKUCsQhyLc9+AU35WYMPRKFQzBC+QxQ3OvWv21A17AxnnTxSKcX8FciVr41lMnEOT/mlvcQ3PTvKgLkC4+cgjpz1Ulu5LrZgnLW5kRVRlSLIboknwBXDFOAK2vfxRBl09Kc/4FMGGS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=McD6Ut5Z; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="McD6Ut5Z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5CAB7C4CEE3; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940718; bh=Jwf3IJv5L+/CRPGF2QZQl1YIeSHddJV1V5U7FHvFfQI=; h=Date:From:To:Cc:Subject:References:From; b=McD6Ut5Z7SZJoobkuakgq8mPZoZJoDZunX3Cy6jcBzxUlMzZIlMdGZY+QBJ6tAeFn rTlfi8ExUpmr4VA/sJib4XKZbwDxRBL0leQpTPD+UwJ+Srj8g6lPZNKpc389x1AFIt NKjSf+wbOBDVnzHzUfvFAeTh++DRh96l4u+y9eswPUCtQhg2qxi1uywWBz62xToTQ2 cps1R0tJjJwvCcCxU5rfmAyYpNu6DC6FucVDEr79CjkVvJgvl8clycfAwo9TQnqjRb 19UkVKOYwRmduwty4EWc0hRsS9PZ1ZYf5UhCCAqbraAUWLfzCE0l4yDR2iRg+ElNrx oc+kKNIGH9Q4g== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoM-00000000Db5-2pIg; Mon, 07 Jul 2025 22:11:58 -0400 Message-ID: <20250708021158.531886085@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:16 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 01/12] unwind_user/sframe: Add support for reading .sframe headers References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf In preparation for unwinding user space stacks with sframe, add basic sframe compile infrastructure and support for reading the .sframe section header. sframe_add_section() reads the header and unconditionally returns an error, so it's not very useful yet. A subsequent patch will improve that. Link: https://lore.kernel.org/all/f27e8463783febfa0dabb0432a3dd6be8ad98412.= 1737511963.git.jpoimboe@kernel.org/ Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- MAINTAINERS | 1 + arch/Kconfig | 3 + include/linux/sframe.h | 40 ++++++++++++ kernel/unwind/Makefile | 3 +- kernel/unwind/sframe.c | 136 +++++++++++++++++++++++++++++++++++++++++ kernel/unwind/sframe.h | 71 +++++++++++++++++++++ 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 include/linux/sframe.h create mode 100644 kernel/unwind/sframe.c create mode 100644 kernel/unwind/sframe.h diff --git a/MAINTAINERS b/MAINTAINERS index 370d780fd5f8..a6a94d2d03b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -25932,6 +25932,7 @@ USERSPACE STACK UNWINDING M: Josh Poimboeuf M: Steven Rostedt S: Maintained +F: include/linux/sframe.h F: include/linux/unwind*.h F: kernel/unwind/ =20 diff --git a/arch/Kconfig b/arch/Kconfig index 2c41d3072910..c54d35e2f860 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -446,6 +446,9 @@ config HAVE_UNWIND_USER_COMPAT_FP bool depends on HAVE_UNWIND_USER_FP =20 +config HAVE_UNWIND_USER_SFRAME + bool + config HAVE_PERF_REGS bool help diff --git a/include/linux/sframe.h b/include/linux/sframe.h new file mode 100644 index 000000000000..0584f661f698 --- /dev/null +++ b/include/linux/sframe.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_SFRAME_H +#define _LINUX_SFRAME_H + +#include +#include + +#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME + +struct sframe_section { + unsigned long sframe_start; + unsigned long sframe_end; + unsigned long text_start; + unsigned long text_end; + + unsigned long fdes_start; + unsigned long fres_start; + unsigned long fres_end; + unsigned int num_fdes; + + signed char ra_off; + signed char fp_off; +}; + +extern int sframe_add_section(unsigned long sframe_start, unsigned long sf= rame_end, + unsigned long text_start, unsigned long text_end); +extern int sframe_remove_section(unsigned long sframe_addr); + +#else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */ + +static inline int sframe_add_section(unsigned long sframe_start, unsigned = long sframe_end, + unsigned long text_start, unsigned long text_end) +{ + return -ENOSYS; +} +static inline int sframe_remove_section(unsigned long sframe_addr) { retur= n -ENOSYS; } + +#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */ + +#endif /* _LINUX_SFRAME_H */ diff --git a/kernel/unwind/Makefile b/kernel/unwind/Makefile index eae37bea54fd..146038165865 100644 --- a/kernel/unwind/Makefile +++ b/kernel/unwind/Makefile @@ -1 +1,2 @@ - obj-$(CONFIG_UNWIND_USER) +=3D user.o deferred.o + obj-$(CONFIG_UNWIND_USER) +=3D user.o deferred.o + obj-$(CONFIG_HAVE_UNWIND_USER_SFRAME) +=3D sframe.o diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c new file mode 100644 index 000000000000..20287f795b36 --- /dev/null +++ b/kernel/unwind/sframe.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Userspace sframe access functions + */ + +#define pr_fmt(fmt) "sframe: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sframe.h" + +#define dbg(fmt, ...) \ + pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) + +static void free_section(struct sframe_section *sec) +{ + kfree(sec); +} + +static int sframe_read_header(struct sframe_section *sec) +{ + unsigned long header_end, fdes_start, fdes_end, fres_start, fres_end; + struct sframe_header shdr; + unsigned int num_fdes; + + if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))= ) { + dbg("header usercopy failed\n"); + return -EFAULT; + } + + if (shdr.preamble.magic !=3D SFRAME_MAGIC || + shdr.preamble.version !=3D SFRAME_VERSION_2 || + !(shdr.preamble.flags & SFRAME_F_FDE_SORTED) || + shdr.auxhdr_len) { + dbg("bad/unsupported sframe header\n"); + return -EINVAL; + } + + if (!shdr.num_fdes || !shdr.num_fres) { + dbg("no fde/fre entries\n"); + return -EINVAL; + } + + header_end =3D sec->sframe_start + SFRAME_HEADER_SIZE(shdr); + if (header_end >=3D sec->sframe_end) { + dbg("header doesn't fit in section\n"); + return -EINVAL; + } + + num_fdes =3D shdr.num_fdes; + fdes_start =3D header_end + shdr.fdes_off; + fdes_end =3D fdes_start + (num_fdes * sizeof(struct sframe_fde)); + + fres_start =3D header_end + shdr.fres_off; + fres_end =3D fres_start + shdr.fre_len; + + if (fres_start < fdes_end || fres_end > sec->sframe_end) { + dbg("inconsistent fde/fre offsets\n"); + return -EINVAL; + } + + sec->num_fdes =3D num_fdes; + sec->fdes_start =3D fdes_start; + sec->fres_start =3D fres_start; + sec->fres_end =3D fres_end; + + sec->ra_off =3D shdr.cfa_fixed_ra_offset; + sec->fp_off =3D shdr.cfa_fixed_fp_offset; + + return 0; +} + +int sframe_add_section(unsigned long sframe_start, unsigned long sframe_en= d, + unsigned long text_start, unsigned long text_end) +{ + struct maple_tree *sframe_mt =3D ¤t->mm->sframe_mt; + struct vm_area_struct *sframe_vma, *text_vma; + struct mm_struct *mm =3D current->mm; + struct sframe_section *sec; + int ret; + + if (!sframe_start || !sframe_end || !text_start || !text_end) { + dbg("zero-length sframe/text address\n"); + return -EINVAL; + } + + scoped_guard(mmap_read_lock, mm) { + sframe_vma =3D vma_lookup(mm, sframe_start); + if (!sframe_vma || sframe_end > sframe_vma->vm_end) { + dbg("bad sframe address (0x%lx - 0x%lx)\n", + sframe_start, sframe_end); + return -EINVAL; + } + + text_vma =3D vma_lookup(mm, text_start); + if (!text_vma || + !(text_vma->vm_flags & VM_EXEC) || + text_end > text_vma->vm_end) { + dbg("bad text address (0x%lx - 0x%lx)\n", + text_start, text_end); + return -EINVAL; + } + } + + sec =3D kzalloc(sizeof(*sec), GFP_KERNEL); + if (!sec) + return -ENOMEM; + + sec->sframe_start =3D sframe_start; + sec->sframe_end =3D sframe_end; + sec->text_start =3D text_start; + sec->text_end =3D text_end; + + ret =3D sframe_read_header(sec); + if (ret) + goto err_free; + + /* TODO nowhere to store it yet - just free it and return an error */ + ret =3D -ENOSYS; + +err_free: + free_section(sec); + return ret; +} + +int sframe_remove_section(unsigned long sframe_start) +{ + return -ENOSYS; +} diff --git a/kernel/unwind/sframe.h b/kernel/unwind/sframe.h new file mode 100644 index 000000000000..e9bfccfaf5b4 --- /dev/null +++ b/kernel/unwind/sframe.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * From https://www.sourceware.org/binutils/docs/sframe-spec.html + */ +#ifndef _SFRAME_H +#define _SFRAME_H + +#include + +#define SFRAME_VERSION_1 1 +#define SFRAME_VERSION_2 2 +#define SFRAME_MAGIC 0xdee2 + +#define SFRAME_F_FDE_SORTED 0x1 +#define SFRAME_F_FRAME_POINTER 0x2 + +#define SFRAME_ABI_AARCH64_ENDIAN_BIG 1 +#define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 +#define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 + +#define SFRAME_FDE_TYPE_PCINC 0 +#define SFRAME_FDE_TYPE_PCMASK 1 + +struct sframe_preamble { + u16 magic; + u8 version; + u8 flags; +} __packed; + +struct sframe_header { + struct sframe_preamble preamble; + u8 abi_arch; + s8 cfa_fixed_fp_offset; + s8 cfa_fixed_ra_offset; + u8 auxhdr_len; + u32 num_fdes; + u32 num_fres; + u32 fre_len; + u32 fdes_off; + u32 fres_off; +} __packed; + +#define SFRAME_HEADER_SIZE(header) \ + ((sizeof(struct sframe_header) + header.auxhdr_len)) + +#define SFRAME_AARCH64_PAUTH_KEY_A 0 +#define SFRAME_AARCH64_PAUTH_KEY_B 1 + +struct sframe_fde { + s32 start_addr; + u32 func_size; + u32 fres_off; + u32 fres_num; + u8 info; + u8 rep_size; + u16 padding; +} __packed; + +#define SFRAME_FUNC_FRE_TYPE(data) (data & 0xf) +#define SFRAME_FUNC_FDE_TYPE(data) ((data >> 4) & 0x1) +#define SFRAME_FUNC_PAUTH_KEY(data) ((data >> 5) & 0x1) + +#define SFRAME_BASE_REG_FP 0 +#define SFRAME_BASE_REG_SP 1 + +#define SFRAME_FRE_CFA_BASE_REG_ID(data) (data & 0x1) +#define SFRAME_FRE_OFFSET_COUNT(data) ((data >> 1) & 0xf) +#define SFRAME_FRE_OFFSET_SIZE(data) ((data >> 5) & 0x3) +#define SFRAME_FRE_MANGLED_RA_P(data) ((data >> 7) & 0x1) + +#endif /* _SFRAME_H */ --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D919A217705; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940718; cv=none; b=SLUbqbqGcQ1SudP3XEtr4sv/R9JC/4LVO5F3Aq5Zw9rA5OAcYeXxZy7IK7rMSzkmtrHFHfd7Wm9v1dx1MgkEx6VgNn1Nz3QOhyYAB+/j5DTDXpl1hWNFJ59cd4j1ibb2e6wxNdKA/JNeyK+OlfpjgqRyNIyp2Fi1fLvbsqlRehc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940718; c=relaxed/simple; bh=vrk74lb0dbKscq8FL04HpWM1hSFFbh97X1kJjRZQ/GY=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=q6a+d60U9Fh5RX2fYJylgLHnOdQB85YILwEcfkG7uyVxAPb77VkV8y5J30/kKRXFYO5pw1AuT/Gp7zWv2/JLBSOosTuoK0SBUvS3EKlp3ArcSIPsgvYn30N3AzfJpr5IivP5Ob5bVc0kz90nVXcydDhBorqU9C4ay5iZhIeMs1k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dxWUMbXU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dxWUMbXU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8658FC4CEFA; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940718; bh=vrk74lb0dbKscq8FL04HpWM1hSFFbh97X1kJjRZQ/GY=; h=Date:From:To:Cc:Subject:References:From; b=dxWUMbXUS3Hbvh+iklY9B/+DdeZgposPgRfU2a7qzi/znqoocNJ9sEjZ/9Hp851k9 W2sKUd9QKQoPXhLryNkOHg/JPvF9seNW3dG2e6DtKHwAvUvzIKYT4DEqDwvolvXr1L JeK4eJ1uoNmb1yP5kaEsZZ1AilKnO39FKbFfnxs3+P4FdoRv3Y6NexD20NViOyBrNu zb+/5jbdFhA8fsl9ODH6NXVgGzL6HcTUc4mEKrc3fe6gEHg7le7NISslGmiHWj2xS+ B/P4FYou+W0o6En0kVtE/zvdVNCr9EuJdDqN7yQ6fNeMT22+Rnqh694sIB/i/OqY8z oCdRI0v79UPug== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoM-00000000DbZ-3aoz; Mon, 07 Jul 2025 22:11:58 -0400 Message-ID: <20250708021158.709625173@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:17 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James , linux-mm@kvack.org Subject: [PATCH v8 02/12] unwind_user/sframe: Store sframe section data in per-mm maple tree References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Associate an sframe section with its mm by adding it to a per-mm maple tree which is indexed by the corresponding text address range. A single sframe section can be associated with multiple text ranges. Cc: linux-mm@kvack.org Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- arch/x86/include/asm/mmu.h | 2 +- include/linux/mm_types.h | 3 +++ include/linux/sframe.h | 13 +++++++++ kernel/fork.c | 10 +++++++ kernel/unwind/sframe.c | 55 +++++++++++++++++++++++++++++++++++--- mm/init-mm.c | 2 ++ 6 files changed, 81 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 0fe9c569d171..227a32899a59 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -87,7 +87,7 @@ typedef struct { .context =3D { \ .ctx_id =3D 1, \ .lock =3D __MUTEX_INITIALIZER(mm.context.lock), \ - } + }, =20 void leave_mm(void); #define leave_mm leave_mm diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index d6b91e8a66d6..4296cabf4afa 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -1206,6 +1206,9 @@ struct mm_struct { #ifdef CONFIG_MM_ID mm_id_t mm_id; #endif /* CONFIG_MM_ID */ +#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME + struct maple_tree sframe_mt; +#endif } __randomize_layout; =20 /* diff --git a/include/linux/sframe.h b/include/linux/sframe.h index 0584f661f698..73bf6f0b30c2 100644 --- a/include/linux/sframe.h +++ b/include/linux/sframe.h @@ -22,18 +22,31 @@ struct sframe_section { signed char fp_off; }; =20 +#define INIT_MM_SFRAME .sframe_mt =3D MTREE_INIT(sframe_mt, 0), +extern void sframe_free_mm(struct mm_struct *mm); + extern int sframe_add_section(unsigned long sframe_start, unsigned long sf= rame_end, unsigned long text_start, unsigned long text_end); extern int sframe_remove_section(unsigned long sframe_addr); =20 +static inline bool current_has_sframe(void) +{ + struct mm_struct *mm =3D current->mm; + + return mm && !mtree_empty(&mm->sframe_mt); +} + #else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */ =20 +#define INIT_MM_SFRAME +static inline void sframe_free_mm(struct mm_struct *mm) {} static inline int sframe_add_section(unsigned long sframe_start, unsigned = long sframe_end, unsigned long text_start, unsigned long text_end) { return -ENOSYS; } static inline int sframe_remove_section(unsigned long sframe_addr) { retur= n -ENOSYS; } +static inline bool current_has_sframe(void) { return false; } =20 #endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */ =20 diff --git a/kernel/fork.c b/kernel/fork.c index 3341d50c61f2..e56daf4e546f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -106,6 +106,7 @@ #include #include #include +#include =20 #include #include @@ -687,6 +688,7 @@ void __mmdrop(struct mm_struct *mm) mm_pasid_drop(mm); mm_destroy_cid(mm); percpu_counter_destroy_many(mm->rss_stat, NR_MM_COUNTERS); + sframe_free_mm(mm); =20 free_mm(mm); } @@ -1024,6 +1026,13 @@ static void mmap_init_lock(struct mm_struct *mm) #endif } =20 +static void mm_init_sframe(struct mm_struct *mm) +{ +#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME + mt_init(&mm->sframe_mt); +#endif +} + static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct = *p, struct user_namespace *user_ns) { @@ -1053,6 +1062,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm= , struct task_struct *p, mm->pmd_huge_pte =3D NULL; #endif mm_init_uprobes_state(mm); + mm_init_sframe(mm); hugetlb_count_init(mm); =20 if (current->mm) { diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 20287f795b36..fa7d87ffd00a 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -122,15 +122,64 @@ int sframe_add_section(unsigned long sframe_start, un= signed long sframe_end, if (ret) goto err_free; =20 - /* TODO nowhere to store it yet - just free it and return an error */ - ret =3D -ENOSYS; + ret =3D mtree_insert_range(sframe_mt, sec->text_start, sec->text_end, sec= , GFP_KERNEL); + if (ret) { + dbg("mtree_insert_range failed: text=3D%lx-%lx\n", + sec->text_start, sec->text_end); + goto err_free; + } + + return 0; =20 err_free: free_section(sec); return ret; } =20 +static int __sframe_remove_section(struct mm_struct *mm, + struct sframe_section *sec) +{ + if (!mtree_erase(&mm->sframe_mt, sec->text_start)) { + dbg("mtree_erase failed: text=3D%lx\n", sec->text_start); + return -EINVAL; + } + + free_section(sec); + + return 0; +} + int sframe_remove_section(unsigned long sframe_start) { - return -ENOSYS; + struct mm_struct *mm =3D current->mm; + struct sframe_section *sec; + unsigned long index =3D 0; + bool found =3D false; + int ret =3D 0; + + mt_for_each(&mm->sframe_mt, sec, index, ULONG_MAX) { + if (sec->sframe_start =3D=3D sframe_start) { + found =3D true; + ret |=3D __sframe_remove_section(mm, sec); + } + } + + if (!found || ret) + return -EINVAL; + + return 0; +} + +void sframe_free_mm(struct mm_struct *mm) +{ + struct sframe_section *sec; + unsigned long index =3D 0; + + if (!mm) + return; + + mt_for_each(&mm->sframe_mt, sec, index, ULONG_MAX) + free_section(sec); + + mtree_destroy(&mm->sframe_mt); } diff --git a/mm/init-mm.c b/mm/init-mm.c index 4600e7605cab..b32fcf167cc2 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -11,6 +11,7 @@ #include #include #include +#include #include =20 #ifndef INIT_MM_CONTEXT @@ -46,6 +47,7 @@ struct mm_struct init_mm =3D { .user_ns =3D &init_user_ns, .cpu_bitmap =3D CPU_BITS_NONE, INIT_MM_CONTEXT(init_mm) + INIT_MM_SFRAME }; =20 void setup_initial_init_mm(void *start_code, void *end_code, --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F781157A72; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=aMSEA2j1JS2KRWEmpzhor+V+LUe4fnNPvJ7fJlWWtjtbseuEAvDd2kc/pVY5Pz1dCBPMMzXu/4ZzwX+Cyn2UIkGBsiXVD7u+x/iqmGDcWXKHgyHiO2y6CgrJVqDlqbxS8/l0ZAtMt17mGEn2AZyCgNkcUZUgWN/R1Ao/d9etytM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=ckTATXCHrvGOC+WZsqQof/3QKuBCz763BBzol3sDKjI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=QoQihxQrEwKT3VfmDk4mazVay0qOzqXjceK4nxB1sdLCZeO/xh0fixhqJ3zBP+22rFA3YfyF5vwuJ/9aJhpMSU5UOXsX1pulNfnDAwYoqsn7PAvBsYX5e8gRRlFx9KxMddO0m1AABcRyO8hIkBc8197cRYSFWbb12XkjcvxAFj8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ofnIIwI7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ofnIIwI7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ACE87C113CF; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940718; bh=ckTATXCHrvGOC+WZsqQof/3QKuBCz763BBzol3sDKjI=; h=Date:From:To:Cc:Subject:References:From; b=ofnIIwI7PS1T8WQKSafoAShNse+Hq8QtKkuNEiJif+r0N2fw3K4arHLO9yfL6gAu4 w4+hDxz519FskchMvlmWy3OiHR6/Z8TJez1DhNSfuGHQeDBaxEHmuhaDDdPifAT9mX oYpKKLgpQqD9nsIwyO3NB+iEWq+0MyTYr/Kqh83xxW3iRAfpmRflP7lijK/r/aO76b IDj7EPOflJc6Ke2qGjQ3OyrI2YFcYyT3ntecH0aPF4nzeQlA2gKxzAPILckuYm1Dhm t48UEppWpt34tF/kXehmzupVbXa0dcbuliLSt+uq95KmlLyWOs4eZJtqs9ra+F53Zg 5jGoKIIhmuwwQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000Dc3-06pt; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021158.877986536@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:18 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 03/12] x86/uaccess: Add unsafe_copy_from_user() implementation References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Add an x86 implementation of unsafe_copy_from_user() similar to the existing unsafe_copy_to_user(). Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- arch/x86/include/asm/uaccess.h | 39 +++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 3a7755c1a441..3caf02d0503e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -599,7 +599,7 @@ _label: \ * We want the unsafe accessors to always be inlined and use * the error labels - thus the macro games. */ -#define unsafe_copy_loop(dst, src, len, type, label) \ +#define unsafe_copy_to_user_loop(dst, src, len, type, label) \ while (len >=3D sizeof(type)) { \ unsafe_put_user(*(type *)(src),(type __user *)(dst),label); \ dst +=3D sizeof(type); \ @@ -607,15 +607,34 @@ _label: \ len -=3D sizeof(type); \ } =20 -#define unsafe_copy_to_user(_dst,_src,_len,label) \ -do { \ - char __user *__ucu_dst =3D (_dst); \ - const char *__ucu_src =3D (_src); \ - size_t __ucu_len =3D (_len); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \ +#define unsafe_copy_to_user(_dst, _src, _len, label) \ +do { \ + void __user *__dst =3D (_dst); \ + const void *__src =3D (_src); \ + size_t __len =3D (_len); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u64, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u32, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u16, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u8, label); \ +} while (0) + +#define unsafe_copy_from_user_loop(dst, src, len, type, label) \ + while (len >=3D sizeof(type)) { \ + unsafe_get_user(*(type *)(dst), (type __user *)(src), label); \ + dst +=3D sizeof(type); \ + src +=3D sizeof(type); \ + len -=3D sizeof(type); \ + } + +#define unsafe_copy_from_user(_dst, _src, _len, label) \ +do { \ + void *__dst =3D (_dst); \ + void __user *__src =3D (_src); \ + size_t __len =3D (_len); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u64, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u32, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u16, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u8, label); \ } while (0) =20 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7577B220F24; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=pDsghLtGhGCB1rU9X52obNCuUmpfQolbkfTA5cP0xsaYOnI7qZ3cUvTINLI0RGes4w06oaYLNJeisapb4AiMKTCKLFyu4mF9K1ReRmJ4IEcSIi/j8OFURn8XoQTVtB3HnwDKo0jhRUVUmzLUv6HPf7ARVojmRoEEAiEbSM7Uogg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=gk3G7a++X/20bDUc/8l0VG/FdRrwlUdlg3WInajGWL8=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=tmQLl9PFqe2v6mB+2oHv1sEMCSXtnbjGIQ+EloiG5gT6iSVKspwCx9dR40Tx0vCbYT1V37HICCiRaZfuZae5vrzbzB9EwzWhcazQzh5r/P57ByvjtD0u7nYbPfhHDiTJaJyeIT/DpwJ/I9/6Lffiwbak2HOlP8B8o5URH6JTPRo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p+CcLwR/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="p+CcLwR/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E148AC4CEF4; Tue, 8 Jul 2025 02:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=gk3G7a++X/20bDUc/8l0VG/FdRrwlUdlg3WInajGWL8=; h=Date:From:To:Cc:Subject:References:From; b=p+CcLwR/ZT/q1g7+M4wXFkeiGwqREifffBgEaa87nc1QY6GFn/MNU+AzVfEQx8p2X hOq6pDQltaApIsWWWr0s/rq3/SHJIlqOmvQlCwb4LU6uIZflDljgA6tZ43PQdWG70n IkPZT9rUfwm7XDS1kw37x9pgJVj8Uyi2YTu5Pif+ZFwSG1a/y5fLVrMwIOGsiAYB3d cT+rcvN7asZ0nUHerfFz8Ka3uzf4lGN7WlSQRWBeEMqZr6bHRRkqAz+JiT+8wik5lc SGYFqR18tcN3/fNOZrVmx0jewQBbA9krw4x5wnVRd56YNVmS+vpO4IwY1Vb1zJjqsi yqwlmSObpGeIg== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000DcX-0ptv; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021159.047835102@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:19 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 04/12] unwind_user/sframe: Add support for reading .sframe contents References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf In preparation for using sframe to unwind user space stacks, add an sframe_find() interface for finding the sframe information associated with a given text address. For performance, use user_read_access_begin() and the corresponding unsafe_*() accessors. Note that use of pr_debug() in uaccess-enabled regions would break noinstr validation, so there aren't any debug messages yet. That will be added in a subsequent commit. Link: https://lore.kernel.org/all/77c0d1ec143bf2a53d66c4ecb190e7e0a576fbfd.= 1737511963.git.jpoimboe@kernel.org/ Link: https://lore.kernel.org/all/b35ca3a3-8de5-4d32-8d30-d4e562f6b0de@linu= x.ibm.com/ Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- include/linux/sframe.h | 5 + kernel/unwind/sframe.c | 311 ++++++++++++++++++++++++++++++++++- kernel/unwind/sframe_debug.h | 35 ++++ 3 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 kernel/unwind/sframe_debug.h diff --git a/include/linux/sframe.h b/include/linux/sframe.h index 73bf6f0b30c2..9a72209696f9 100644 --- a/include/linux/sframe.h +++ b/include/linux/sframe.h @@ -3,11 +3,14 @@ #define _LINUX_SFRAME_H =20 #include +#include #include =20 #ifdef CONFIG_HAVE_UNWIND_USER_SFRAME =20 struct sframe_section { + struct rcu_head rcu; + unsigned long sframe_start; unsigned long sframe_end; unsigned long text_start; @@ -28,6 +31,7 @@ extern void sframe_free_mm(struct mm_struct *mm); extern int sframe_add_section(unsigned long sframe_start, unsigned long sf= rame_end, unsigned long text_start, unsigned long text_end); extern int sframe_remove_section(unsigned long sframe_addr); +extern int sframe_find(unsigned long ip, struct unwind_user_frame *frame); =20 static inline bool current_has_sframe(void) { @@ -46,6 +50,7 @@ static inline int sframe_add_section(unsigned long sframe= _start, unsigned long s return -ENOSYS; } static inline int sframe_remove_section(unsigned long sframe_addr) { retur= n -ENOSYS; } +static inline int sframe_find(unsigned long ip, struct unwind_user_frame *= frame) { return -ENOSYS; } static inline bool current_has_sframe(void) { return false; } =20 #endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */ diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index fa7d87ffd00a..b10420d19840 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -15,9 +15,303 @@ #include =20 #include "sframe.h" +#include "sframe_debug.h" =20 -#define dbg(fmt, ...) \ - pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) +struct sframe_fre { + unsigned int size; + u32 ip_off; + s32 cfa_off; + s32 ra_off; + s32 fp_off; + u8 info; +}; + +DEFINE_STATIC_SRCU(sframe_srcu); + +static __always_inline unsigned char fre_type_to_size(unsigned char fre_ty= pe) +{ + if (fre_type > 2) + return 0; + return 1 << fre_type; +} + +static __always_inline unsigned char offset_size_enum_to_size(unsigned cha= r off_size) +{ + if (off_size > 2) + return 0; + return 1 << off_size; +} + +static __always_inline int __read_fde(struct sframe_section *sec, + unsigned int fde_num, + struct sframe_fde *fde) +{ + unsigned long fde_addr, ip; + + fde_addr =3D sec->fdes_start + (fde_num * sizeof(struct sframe_fde)); + unsafe_copy_from_user(fde, (void __user *)fde_addr, + sizeof(struct sframe_fde), Efault); + + ip =3D sec->sframe_start + fde->start_addr; + if (ip < sec->text_start || ip > sec->text_end) + return -EINVAL; + + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int __find_fde(struct sframe_section *sec, + unsigned long ip, + struct sframe_fde *fde) +{ + s32 ip_off, func_off_low =3D S32_MIN, func_off_high =3D S32_MAX; + struct sframe_fde __user *first, *low, *high, *found =3D NULL; + int ret; + + ip_off =3D ip - sec->sframe_start; + + first =3D (void __user *)sec->fdes_start; + low =3D first; + high =3D first + sec->num_fdes - 1; + + while (low <=3D high) { + struct sframe_fde __user *mid; + s32 func_off; + + mid =3D low + ((high - low) / 2); + + unsafe_get_user(func_off, (s32 __user *)mid, Efault); + + if (ip_off >=3D func_off) { + if (func_off < func_off_low) + return -EFAULT; + + func_off_low =3D func_off; + + found =3D mid; + low =3D mid + 1; + } else { + if (func_off > func_off_high) + return -EFAULT; + + func_off_high =3D func_off; + + high =3D mid - 1; + } + } + + if (!found) + return -EINVAL; + + ret =3D __read_fde(sec, found - first, fde); + if (ret) + return ret; + + /* make sure it's not in a gap */ + if (ip_off < fde->start_addr || ip_off >=3D fde->start_addr + fde->func_s= ize) + return -EINVAL; + + return 0; + +Efault: + return -EFAULT; +} + +#define ____UNSAFE_GET_USER_INC(to, from, type, label) \ +({ \ + type __to; \ + unsafe_get_user(__to, (type __user *)from, label); \ + from +=3D sizeof(__to); \ + to =3D __to; \ +}) + +#define __UNSAFE_GET_USER_INC(to, from, size, label, u_or_s) \ +({ \ + switch (size) { \ + case 1: \ + ____UNSAFE_GET_USER_INC(to, from, u_or_s##8, label); \ + break; \ + case 2: \ + ____UNSAFE_GET_USER_INC(to, from, u_or_s##16, label); \ + break; \ + case 4: \ + ____UNSAFE_GET_USER_INC(to, from, u_or_s##32, label); \ + break; \ + default: \ + return -EFAULT; \ + } \ +}) + +#define UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label) \ + __UNSAFE_GET_USER_INC(to, from, size, label, u) + +#define UNSAFE_GET_USER_SIGNED_INC(to, from, size, label) \ + __UNSAFE_GET_USER_INC(to, from, size, label, s) + +#define UNSAFE_GET_USER_INC(to, from, size, label) \ + _Generic(to, \ + u8: UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \ + u16: UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \ + u32: UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \ + s8: UNSAFE_GET_USER_SIGNED_INC(to, from, size, label), \ + s16: UNSAFE_GET_USER_SIGNED_INC(to, from, size, label), \ + s32: UNSAFE_GET_USER_SIGNED_INC(to, from, size, label)) + +static __always_inline int __read_fre(struct sframe_section *sec, + struct sframe_fde *fde, + unsigned long fre_addr, + struct sframe_fre *fre) +{ + unsigned char fde_type =3D SFRAME_FUNC_FDE_TYPE(fde->info); + unsigned char fre_type =3D SFRAME_FUNC_FRE_TYPE(fde->info); + unsigned char offset_count, offset_size; + s32 cfa_off, ra_off, fp_off; + unsigned long cur =3D fre_addr; + unsigned char addr_size; + u32 ip_off; + u8 info; + + addr_size =3D fre_type_to_size(fre_type); + if (!addr_size) + return -EFAULT; + + if (fre_addr + addr_size + 1 > sec->fres_end) + return -EFAULT; + + UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault); + if (fde_type =3D=3D SFRAME_FDE_TYPE_PCINC && ip_off > fde->func_size) + return -EFAULT; + + UNSAFE_GET_USER_INC(info, cur, 1, Efault); + offset_count =3D SFRAME_FRE_OFFSET_COUNT(info); + offset_size =3D offset_size_enum_to_size(SFRAME_FRE_OFFSET_SIZE(info)); + if (!offset_count || !offset_size) + return -EFAULT; + + if (cur + (offset_count * offset_size) > sec->fres_end) + return -EFAULT; + + fre->size =3D addr_size + 1 + (offset_count * offset_size); + + UNSAFE_GET_USER_INC(cfa_off, cur, offset_size, Efault); + offset_count--; + + ra_off =3D sec->ra_off; + if (!ra_off) { + if (!offset_count--) + return -EFAULT; + + UNSAFE_GET_USER_INC(ra_off, cur, offset_size, Efault); + } + + fp_off =3D sec->fp_off; + if (!fp_off && offset_count) { + offset_count--; + UNSAFE_GET_USER_INC(fp_off, cur, offset_size, Efault); + } + + if (offset_count) + return -EFAULT; + + fre->ip_off =3D ip_off; + fre->cfa_off =3D cfa_off; + fre->ra_off =3D ra_off; + fre->fp_off =3D fp_off; + fre->info =3D info; + + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int __find_fre(struct sframe_section *sec, + struct sframe_fde *fde, unsigned long ip, + struct unwind_user_frame *frame) +{ + unsigned char fde_type =3D SFRAME_FUNC_FDE_TYPE(fde->info); + struct sframe_fre *fre, *prev_fre =3D NULL; + struct sframe_fre fres[2]; + unsigned long fre_addr; + bool which =3D false; + unsigned int i; + u32 ip_off; + + ip_off =3D ip - (sec->sframe_start + fde->start_addr); + + if (fde_type =3D=3D SFRAME_FDE_TYPE_PCMASK) + ip_off %=3D fde->rep_size; + + fre_addr =3D sec->fres_start + fde->fres_off; + + for (i =3D 0; i < fde->fres_num; i++) { + int ret; + + /* + * Alternate between the two fre_addr[] entries for 'fre' and + * 'prev_fre'. + */ + fre =3D which ? fres : fres + 1; + which =3D !which; + + ret =3D __read_fre(sec, fde, fre_addr, fre); + if (ret) + return ret; + + fre_addr +=3D fre->size; + + if (prev_fre && fre->ip_off <=3D prev_fre->ip_off) + return -EFAULT; + + if (fre->ip_off > ip_off) + break; + + prev_fre =3D fre; + } + + if (!prev_fre) + return -EINVAL; + fre =3D prev_fre; + + frame->cfa_off =3D fre->cfa_off; + frame->ra_off =3D fre->ra_off; + frame->fp_off =3D fre->fp_off; + frame->use_fp =3D SFRAME_FRE_CFA_BASE_REG_ID(fre->info) =3D=3D SFRAME_BA= SE_REG_FP; + + return 0; +} + +int sframe_find(unsigned long ip, struct unwind_user_frame *frame) +{ + struct mm_struct *mm =3D current->mm; + struct sframe_section *sec; + struct sframe_fde fde; + int ret; + + if (!mm) + return -EINVAL; + + guard(srcu)(&sframe_srcu); + + sec =3D mtree_load(&mm->sframe_mt, ip); + if (!sec) + return -EINVAL; + + if (!user_read_access_begin((void __user *)sec->sframe_start, + sec->sframe_end - sec->sframe_start)) + return -EFAULT; + + ret =3D __find_fde(sec, ip, &fde); + if (ret) + goto end; + + ret =3D __find_fre(sec, &fde, ip, frame); +end: + user_read_access_end(); + return ret; +} =20 static void free_section(struct sframe_section *sec) { @@ -119,8 +413,10 @@ int sframe_add_section(unsigned long sframe_start, uns= igned long sframe_end, sec->text_end =3D text_end; =20 ret =3D sframe_read_header(sec); - if (ret) + if (ret) { + dbg_print_header(sec); goto err_free; + } =20 ret =3D mtree_insert_range(sframe_mt, sec->text_start, sec->text_end, sec= , GFP_KERNEL); if (ret) { @@ -136,6 +432,13 @@ int sframe_add_section(unsigned long sframe_start, uns= igned long sframe_end, return ret; } =20 +static void sframe_free_srcu(struct rcu_head *rcu) +{ + struct sframe_section *sec =3D container_of(rcu, struct sframe_section, r= cu); + + free_section(sec); +} + static int __sframe_remove_section(struct mm_struct *mm, struct sframe_section *sec) { @@ -144,7 +447,7 @@ static int __sframe_remove_section(struct mm_struct *mm, return -EINVAL; } =20 - free_section(sec); + call_srcu(&sframe_srcu, &sec->rcu, sframe_free_srcu); =20 return 0; } diff --git a/kernel/unwind/sframe_debug.h b/kernel/unwind/sframe_debug.h new file mode 100644 index 000000000000..055c8c8fae24 --- /dev/null +++ b/kernel/unwind/sframe_debug.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SFRAME_DEBUG_H +#define _SFRAME_DEBUG_H + +#include +#include "sframe.h" + +#ifdef CONFIG_DYNAMIC_DEBUG + +#define dbg(fmt, ...) \ + pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) + +static __always_inline void dbg_print_header(struct sframe_section *sec) +{ + unsigned long fdes_end; + + fdes_end =3D sec->fdes_start + (sec->num_fdes * sizeof(struct sframe_fde)= ); + + dbg("SEC: sframe:0x%lx-0x%lx text:0x%lx-0x%lx " + "fdes:0x%lx-0x%lx fres:0x%lx-0x%lx " + "ra_off:%d fp_off:%d\n", + sec->sframe_start, sec->sframe_end, sec->text_start, sec->text_end, + sec->fdes_start, fdes_end, sec->fres_start, sec->fres_end, + sec->ra_off, sec->fp_off); +} + +#else /* !CONFIG_DYNAMIC_DEBUG */ + +#define dbg(args...) no_printk(args) + +static inline void dbg_print_header(struct sframe_section *sec) {} + +#endif /* !CONFIG_DYNAMIC_DEBUG */ + +#endif /* _SFRAME_DEBUG_H */ --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A1410223DF5; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=FoEoL87vgdDkaO59omhOGZVAsIJFnXOi6eludxZwGHD8sed1D49a+hj85RkWfbh0jxKuCOm5ZQ0XLGmf80bEEGe1DaLnKe2bwh8AY1ZyUUt2k7Obkl/MFKPX+3S3yKvWZco/XkELnO696cjz41hD6XV0W2a5VVIkE44771VP4bw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=w3zlkwOetCuL4IjiyP6cPFfl8DekoC294wC1K1nFMzE=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=QOEoQuwogdzac+EqEfE4D05bmbjUqbc8cTpj8dKlO9NrfDEv/GMjDxVtHS1L9ysVTuElCT+09zV85TRrz04KCa840re7r/+BIoK/teMHlDuFrId4rhYYUBod7HlyHs9Vn3EoytplFa8HXOiukoOjP0oMspDr/82a9Prp4S54sYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=teymkXLY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="teymkXLY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35667C4CEF8; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=w3zlkwOetCuL4IjiyP6cPFfl8DekoC294wC1K1nFMzE=; h=Date:From:To:Cc:Subject:References:From; b=teymkXLYAC8/0Wos0/V+ujuJ0BnlPwtReFwIEPwScBvCSV1W1WyPa1ZGCipziOSwU OeWj/fq7QelGZGkK4A19lfH+4lBc2djRdC6xPrgb0ZoVgjUC4A8qjMmlHCH4KMvqzT QBbL9hDkmf/qOHbnmhkyG+PeEUBL1xDn1JGJhZhXRb3tEEbN+BWor7qQJeR4+BlCWT xK6SWDljvUIHl9fiHE3SgZXL9pyjZJaBj2WXcdmzOOzeYL2eHKk6gkrv27e2oO/nRj 2i4/SOWJIDS8QpuvLZzs6Aye4uHeozaT68WQR0kHG8wcRzVNUbfw3RdYF7dfzS///i qDwwJnFHGekvg== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000Dd1-1XOo; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021159.219332581@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:20 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 05/12] unwind_user/sframe: Detect .sframe sections in executables References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf When loading an ELF executable, automatically detect an .sframe section and associate it with the mm_struct. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- fs/binfmt_elf.c | 49 +++++++++++++++++++++++++++++++++++++--- include/uapi/linux/elf.h | 1 + 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index a43363d593e5..e7128d026ec0 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include =20 @@ -622,6 +623,21 @@ static inline int make_prot(u32 p_flags, struct arch_e= lf_state *arch_state, return arch_elf_adjust_prot(prot, arch_state, has_interp, is_interp); } =20 +static void elf_add_sframe(struct elf_phdr *text, struct elf_phdr *sframe, + unsigned long base_addr) +{ + unsigned long sframe_start, sframe_end, text_start, text_end; + + sframe_start =3D base_addr + sframe->p_vaddr; + sframe_end =3D sframe_start + sframe->p_memsz; + + text_start =3D base_addr + text->p_vaddr; + text_end =3D text_start + text->p_memsz; + + /* Ignore return value, sframe section isn't critical */ + sframe_add_section(sframe_start, sframe_end, text_start, text_end); +} + /* This is much more generalized than the library routine read function, so we keep this separate. Technically the library read function is only provided so that we can read a.out libraries that have @@ -632,7 +648,7 @@ static unsigned long load_elf_interp(struct elfhdr *int= erp_elf_ex, unsigned long no_base, struct elf_phdr *interp_elf_phdata, struct arch_elf_state *arch_state) { - struct elf_phdr *eppnt; + struct elf_phdr *eppnt, *sframe_phdr =3D NULL; unsigned long load_addr =3D 0; int load_addr_set =3D 0; unsigned long error =3D ~0UL; @@ -658,7 +674,8 @@ static unsigned long load_elf_interp(struct elfhdr *int= erp_elf_ex, =20 eppnt =3D interp_elf_phdata; for (i =3D 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { - if (eppnt->p_type =3D=3D PT_LOAD) { + switch (eppnt->p_type) { + case PT_LOAD: { int elf_type =3D MAP_PRIVATE; int elf_prot =3D make_prot(eppnt->p_flags, arch_state, true, true); @@ -697,6 +714,20 @@ static unsigned long load_elf_interp(struct elfhdr *in= terp_elf_ex, error =3D -ENOMEM; goto out; } + break; + } + case PT_GNU_SFRAME: + sframe_phdr =3D eppnt; + break; + } + } + + if (sframe_phdr) { + eppnt =3D interp_elf_phdata; + for (i =3D 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { + if (eppnt->p_flags & PF_X) { + elf_add_sframe(eppnt, sframe_phdr, load_addr); + } } } =20 @@ -821,7 +852,7 @@ static int load_elf_binary(struct linux_binprm *bprm) int first_pt_load =3D 1; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata =3D NULL; - struct elf_phdr *elf_property_phdata =3D NULL; + struct elf_phdr *elf_property_phdata =3D NULL, *sframe_phdr =3D NULL; unsigned long elf_brk; bool brk_moved =3D false; int retval, i; @@ -930,6 +961,10 @@ static int load_elf_binary(struct linux_binprm *bprm) executable_stack =3D EXSTACK_DISABLE_X; break; =20 + case PT_GNU_SFRAME: + sframe_phdr =3D elf_ppnt; + break; + case PT_LOPROC ... PT_HIPROC: retval =3D arch_elf_pt_proc(elf_ex, elf_ppnt, bprm->file, false, @@ -1227,6 +1262,14 @@ static int load_elf_binary(struct linux_binprm *bprm) elf_brk =3D k; } =20 + if (sframe_phdr) { + for (i =3D 0, elf_ppnt =3D elf_phdata; + i < elf_ex->e_phnum; i++, elf_ppnt++) { + if ((elf_ppnt->p_flags & PF_X)) + elf_add_sframe(elf_ppnt, sframe_phdr, load_bias); + } + } + e_entry =3D elf_ex->e_entry + load_bias; phdr_addr +=3D load_bias; elf_brk +=3D load_bias; diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 819ded2d39de..92c16c94fca8 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -41,6 +41,7 @@ typedef __u16 Elf64_Versym; #define PT_GNU_STACK (PT_LOOS + 0x474e551) #define PT_GNU_RELRO (PT_LOOS + 0x474e552) #define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) +#define PT_GNU_SFRAME (PT_LOOS + 0x474e554) =20 =20 /* ARM MTE memory tag segment type */ --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6889621FF5F; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=WBzRCe0F9UdoSjELX3mmRFgs3BQoeT1UzhtGyw6VAA3fW7zq3r0R2H4AG50szXMXqSTRQeahzPovj2BohvlUUabin2q9mpk/P8fKxrbTW3HVVXM4BeBhv/9pNrpRPJzEFualjiXWrapNcVYmmByOTEagbTPJ1ZnVREOv2ZQN4jI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=mCPJ2wJkMSxHj5eWYMxvQ3cKpVx1XsIVQRcDHIz7ptQ=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=ksYGLiTGyeAUC6vxUz5t1MFYiINkWhSliMp+4AB7mrtsJ/I3F3GH3/auPR6L6kuJzbNw2nHKA9RNT36NhBPxJdRem3ADdx4mG+3eH4PnqL10buiaBdgcbKE36dD6a6syyJDhQ3+y5FwQJARr8P9eVEE3vp1brjtXAh6/gImA7DU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WRjxgpx7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WRjxgpx7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 348A3C4CEE3; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=mCPJ2wJkMSxHj5eWYMxvQ3cKpVx1XsIVQRcDHIz7ptQ=; h=Date:From:To:Cc:Subject:References:From; b=WRjxgpx7ixr/OLWzER0sgV925ibErSPLN39Gg6pPZ2p1j8RrcCC3T/Xys/P8IqgN4 R/1ZIvIq4ep9yt41d/6ooDm4+X/D5PLebifZHKpchhJ43xO97D9qW4m4uKyAm5oBKu CLB0XXNgCOzyYwZi9LNPdYfz0IgUVdjnJ8b5xsUbcXC7bk+yhq1pS5BM/EULP08iLZ DYOMhavsW92Smv6Hl7OkaEaFDkNhuw30LB23jQWqc8eLSrI3JzZ0wHh16me8wOxuGG F8sAn9OhvOwjLrvl5ObQIkuGTDdViS/CoRj/QKXQC5uXSpGldlDkGaEYnh5dKl4jEn y1iykIam4u2ZQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000DdW-2EZU; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021159.386608979@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:21 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 06/12] unwind_user/sframe: Wire up unwind_user to sframe References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Now that the sframe infrastructure is fully in place, make it work by hooking it up to the unwind_user interface. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- arch/Kconfig | 1 + include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 25 ++++++++++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index c54d35e2f860..0c6056ef13de 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -448,6 +448,7 @@ config HAVE_UNWIND_USER_COMPAT_FP =20 config HAVE_UNWIND_USER_SFRAME bool + select UNWIND_USER =20 config HAVE_PERF_REGS bool diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 0b6563951ca4..4d50476e950e 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -13,6 +13,7 @@ enum unwind_user_type { UNWIND_USER_TYPE_NONE, UNWIND_USER_TYPE_FP, UNWIND_USER_TYPE_COMPAT_FP, + UNWIND_USER_TYPE_SFRAME, }; =20 struct unwind_stacktrace { diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 249d9e32fad7..6e7ca9f1293a 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -7,6 +7,7 @@ #include #include #include +#include =20 static struct unwind_user_frame fp_frame =3D { ARCH_INIT_USER_FP_FRAME @@ -31,6 +32,12 @@ static inline bool compat_fp_state(struct unwind_user_st= ate *state) state->type =3D=3D UNWIND_USER_TYPE_COMPAT_FP; } =20 +static inline bool sframe_state(struct unwind_user_state *state) +{ + return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_SFRAME) && + state->type =3D=3D UNWIND_USER_TYPE_SFRAME; +} + #define unwind_get_user_long(to, from, state) \ ({ \ int __ret; \ @@ -44,18 +51,28 @@ static inline bool compat_fp_state(struct unwind_user_s= tate *state) static int unwind_user_next(struct unwind_user_state *state) { struct unwind_user_frame *frame; + struct unwind_user_frame _frame; unsigned long cfa =3D 0, fp, ra =3D 0; unsigned int shift; =20 if (state->done) return -EINVAL; =20 - if (compat_fp_state(state)) + if (compat_fp_state(state)) { frame =3D &compat_fp_frame; - else if (fp_state(state)) + } else if (sframe_state(state)) { + /* sframe expects the frame to be local storage */ + frame =3D &_frame; + if (sframe_find(state->ip, frame)) { + if (!IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) + goto done; + frame =3D &fp_frame; + } + } else if (fp_state(state)) { frame =3D &fp_frame; - else + } else { goto done; + } =20 if (frame->use_fp) { if (state->fp < state->sp) @@ -111,6 +128,8 @@ static int unwind_user_start(struct unwind_user_state *= state) =20 if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_COMPAT_FP) && in_compat_mode(regs)) state->type =3D UNWIND_USER_TYPE_COMPAT_FP; + else if (current_has_sframe()) + state->type =3D UNWIND_USER_TYPE_SFRAME; else if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) state->type =3D UNWIND_USER_TYPE_FP; else --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ACF2B224AF2; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=epyRj8DQN+V461jRqN3wKVvj/HzK3Z2PcOmGZi1Hgt+NYULGgcg1E843jTXLbpVdww/beZGL1SpL5Eb/Jkc1+JQLqMxxzS5ts+afnfNePVOSQkj4UwHmcV1X2+7ewXQNI7h5Od2pzeqc/Ek0vPwDwF9mnz34NXHtZuo/avh79pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=IEeF1XmOFvet0cAU5DreYcr/1OJVi6UMuV3x6isQ67c=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=sb0YB2rH1VVUefshvrLvpJb1hw+kOJyPRTZNk9/xvrOTnVfVdHip2ajvFTglsUrXxQchA241MnfvnyG5CUOYx0OMwT1OijaZlfE8IAw/TQv+xjelLq+1XTMxWFktVscZQaVQArg8NLkCNqGgqp7GRK5zAbGhAi421afd6Od4Ftw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uCkhzSiQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uCkhzSiQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 62E86C116C6; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=IEeF1XmOFvet0cAU5DreYcr/1OJVi6UMuV3x6isQ67c=; h=Date:From:To:Cc:Subject:References:From; b=uCkhzSiQKmFrmco8yP7xlCWCh9jEpI4C2UECYcSuKnH4tIW7KgKDNCycqD5XjwWXn tCiKS5z3EvoZCkl776kV/wTee+ITriIkm4IidxoycIu6Pd424/gWOdJKoUjGzuyFbx vLkmRHWWChVGjLUjEeHzawKSdiXcwKHyVHDbshBvR62pEoUArab2EnJV4YXEBycUnF zLWdXFZHxth4jzruG/LT+EVf3YAuStMxq+fiSj7pquD+bCsUSLXxq6PgbPN6w6sPZR tGgbU2RHtj7LBLhR5YSBemdHLSYV2LwVchaj/cZnTFSY+enM3kJlPRes8ZVgHshofB kOuIWdPT0cMjg== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000De0-2wJ7; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021159.552828535@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:22 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 07/12] unwind_user/sframe/x86: Enable sframe unwinding on x86 References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf The x86 sframe 2.0 implementation works fairly well, starting with binutils 2.41 (though some bugs are getting fixed in later versions). Enable it. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 17d4094c821b..8a382a6b9be3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -304,6 +304,7 @@ config X86 select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_UNWIND_USER_COMPAT_FP if IA32_EMULATION select HAVE_UNWIND_USER_FP if X86_64 + select HAVE_UNWIND_USER_SFRAME if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select VDSO_GETRANDOM if X86_64 --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A69B32248BF; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=nszM96rxXygK4oKdfO02w5+muVvVadHBB8nRiso5x/4EUW+BpyUtN0QkdM1K9t2vkoKxAH5ysRZdAwQJaLGjGg/juuKDMwJbjbab6lhm2xQDIOFvjgiRcToOT2AW1W18y5obGUrqs7dxjhQp3+yWVZYr4ruLXkJBn+0oMc0VSmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=tQh371Xu4aNv634IWnbNpzI8g0gGO4AVuobSDHJ5Ps4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=qe2MWOLdmDCd9g3g+xVRI0eBb2HIgPLu8fYfSpwLwRLEbUWPrTy+R9xj5QQRapnFWp//8zXeBWkflcl3huxwaCtmkd7EGy5Pc2fqZYaSa1Z5kF/Usscrd4k8tpk69k4vOfXbocH/cQ6jswbfNWvdtPJxh59kTCuyFmBlq5fUces= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YPncEIZN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YPncEIZN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 85FFAC4CEF5; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=tQh371Xu4aNv634IWnbNpzI8g0gGO4AVuobSDHJ5Ps4=; h=Date:From:To:Cc:Subject:References:From; b=YPncEIZNeWYyU+Bt9rm/KZTt696DmMS0QKxERpoPjndVNQK3Oa6m4/ckgpS+5ylj6 EscF0muNd5qA10L6Fs34V5HulXr3LzTuz0gu1Uv3Mx4Agq9kZNQFd+PzPiYV9jotzB 1tAqgkqb8RaFVi9HfnEFEbXLBAGKirrOuRNKENm7kgW/i+q8nEwyf/9KTyxv8tqnU2 C7nMQeo1DGU8qH4TBUy5Z35HGdobSU41BzzM507ZzfoX9DJZMyi/eld1OLy4pyRlkY xLYAuNwgYp3ENA+nm+zeaic4Z+ex3OFU5mY7vflH1150Pg6n6eRRNyZU4eNpOWDNdO p2MgRd8aTVj0Q== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoN-00000000DeW-3dri; Mon, 07 Jul 2025 22:11:59 -0400 Message-ID: <20250708021159.719618907@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:23 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 08/12] unwind_user/sframe: Remove .sframe section on detected corruption References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf To avoid continued attempted use of a bad .sframe section, remove it on demand when the first sign of corruption is detected. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- kernel/unwind/sframe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index b10420d19840..f246ead6c2a0 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -310,6 +310,10 @@ int sframe_find(unsigned long ip, struct unwind_user_f= rame *frame) ret =3D __find_fre(sec, &fde, ip, frame); end: user_read_access_end(); + + if (ret =3D=3D -EFAULT) + WARN_ON_ONCE(sframe_remove_section(sec->sframe_start)); + return ret; } =20 --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D359F2264B2; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; cv=none; b=iDh3HU2TBwV27NWQvpEWi/843pXk4bhD2nS8I8WpGJVvJO0YWzXrGmMS8tEB0+Jdm655MSs3OKuJbFJdfSZx59j+nBLn3eEyFAWB47qt1Xo8AO8DxqPAYHCNOP6PCm7AGsmabyyoa1mvbE4s7MoWFDvSvtVCk+A7/P1SJNalmkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940719; c=relaxed/simple; bh=+1dKUkXeGNCMo2SsOx0RVb/skigBKBZOQ6KCmMD4/Gk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=WUHWEBfWTB+pmr3Bz2CU852Nq703bMRhc+w2ewvcJYe0pXqh7+jOka3mNeuTGGwY8YZznlI/aStJVZfMTzet0C6VEgVusrJk2SKUY+ouYDe9rwyFdpLjs3bRLPx7moCvLNMYKCkKDWp9MBbJFnUcy2qEU6y/xoHDjBGb0wnOu9M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mFOLG9VA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mFOLG9VA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B3633C4CEF4; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940719; bh=+1dKUkXeGNCMo2SsOx0RVb/skigBKBZOQ6KCmMD4/Gk=; h=Date:From:To:Cc:Subject:References:From; b=mFOLG9VA4dPKzffvcdJ96kiN3gm1LjnqC+daOwiuMsecExk5/wmhJIWtdX4VZyv1d jdFebOzEY3jgoJE0rRN941AZHTaQDtUmrLDc5KbdysBrV4FvwkElhT33RZ4wIt4/Ae saq3uo1aujuzJehUQoKGNH9VBycoQN4TDBSwNCm9+N3wnSoxHF1lRV0S3bsPnrQfXj SUlCe46VUNmyzrFcRZZAG5j7JX1i0p3xugwWgtM+XMO+9EzCiREvZfE+I+hdWEWOjB 6RfElJDzBgCNQZirfO54x/Nt79pqOAJPHDs/MUETZullt58088Ho771YBmRrxNRPQT 2vE3Q2uXzy3ng== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoO-00000000Df2-09ow; Mon, 07 Jul 2025 22:12:00 -0400 Message-ID: <20250708021159.889174831@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:24 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 09/12] unwind_user/sframe: Show file name in debug output References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf When debugging sframe issues, the error messages aren't all that helpful without knowing what file a corresponding .sframe section belongs to. Prefix debug output strings with the file name. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- include/linux/sframe.h | 4 +++- kernel/unwind/sframe.c | 23 ++++++++++-------- kernel/unwind/sframe_debug.h | 45 +++++++++++++++++++++++++++++++----- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/include/linux/sframe.h b/include/linux/sframe.h index 9a72209696f9..b79c5ec09229 100644 --- a/include/linux/sframe.h +++ b/include/linux/sframe.h @@ -10,7 +10,9 @@ =20 struct sframe_section { struct rcu_head rcu; - +#ifdef CONFIG_DYNAMIC_DEBUG + const char *filename; +#endif unsigned long sframe_start; unsigned long sframe_end; unsigned long text_start; diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index f246ead6c2a0..66d3ba3c8389 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -311,14 +311,17 @@ int sframe_find(unsigned long ip, struct unwind_user_= frame *frame) end: user_read_access_end(); =20 - if (ret =3D=3D -EFAULT) + if (ret =3D=3D -EFAULT) { + dbg_sec("removing bad .sframe section\n"); WARN_ON_ONCE(sframe_remove_section(sec->sframe_start)); + } =20 return ret; } =20 static void free_section(struct sframe_section *sec) { + dbg_free(sec); kfree(sec); } =20 @@ -329,7 +332,7 @@ static int sframe_read_header(struct sframe_section *se= c) unsigned int num_fdes; =20 if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))= ) { - dbg("header usercopy failed\n"); + dbg_sec("header usercopy failed\n"); return -EFAULT; } =20 @@ -337,18 +340,18 @@ static int sframe_read_header(struct sframe_section *= sec) shdr.preamble.version !=3D SFRAME_VERSION_2 || !(shdr.preamble.flags & SFRAME_F_FDE_SORTED) || shdr.auxhdr_len) { - dbg("bad/unsupported sframe header\n"); + dbg_sec("bad/unsupported sframe header\n"); return -EINVAL; } =20 if (!shdr.num_fdes || !shdr.num_fres) { - dbg("no fde/fre entries\n"); + dbg_sec("no fde/fre entries\n"); return -EINVAL; } =20 header_end =3D sec->sframe_start + SFRAME_HEADER_SIZE(shdr); if (header_end >=3D sec->sframe_end) { - dbg("header doesn't fit in section\n"); + dbg_sec("header doesn't fit in section\n"); return -EINVAL; } =20 @@ -360,7 +363,7 @@ static int sframe_read_header(struct sframe_section *se= c) fres_end =3D fres_start + shdr.fre_len; =20 if (fres_start < fdes_end || fres_end > sec->sframe_end) { - dbg("inconsistent fde/fre offsets\n"); + dbg_sec("inconsistent fde/fre offsets\n"); return -EINVAL; } =20 @@ -416,6 +419,8 @@ int sframe_add_section(unsigned long sframe_start, unsi= gned long sframe_end, sec->text_start =3D text_start; sec->text_end =3D text_end; =20 + dbg_init(sec); + ret =3D sframe_read_header(sec); if (ret) { dbg_print_header(sec); @@ -424,8 +429,8 @@ int sframe_add_section(unsigned long sframe_start, unsi= gned long sframe_end, =20 ret =3D mtree_insert_range(sframe_mt, sec->text_start, sec->text_end, sec= , GFP_KERNEL); if (ret) { - dbg("mtree_insert_range failed: text=3D%lx-%lx\n", - sec->text_start, sec->text_end); + dbg_sec("mtree_insert_range failed: text=3D%lx-%lx\n", + sec->text_start, sec->text_end); goto err_free; } =20 @@ -447,7 +452,7 @@ static int __sframe_remove_section(struct mm_struct *mm, struct sframe_section *sec) { if (!mtree_erase(&mm->sframe_mt, sec->text_start)) { - dbg("mtree_erase failed: text=3D%lx\n", sec->text_start); + dbg_sec("mtree_erase failed: text=3D%lx\n", sec->text_start); return -EINVAL; } =20 diff --git a/kernel/unwind/sframe_debug.h b/kernel/unwind/sframe_debug.h index 055c8c8fae24..7794bf0bd78c 100644 --- a/kernel/unwind/sframe_debug.h +++ b/kernel/unwind/sframe_debug.h @@ -10,26 +10,59 @@ #define dbg(fmt, ...) \ pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) =20 +#define dbg_sec(fmt, ...) \ + dbg("%s: " fmt, sec->filename, ##__VA_ARGS__) + static __always_inline void dbg_print_header(struct sframe_section *sec) { unsigned long fdes_end; =20 fdes_end =3D sec->fdes_start + (sec->num_fdes * sizeof(struct sframe_fde)= ); =20 - dbg("SEC: sframe:0x%lx-0x%lx text:0x%lx-0x%lx " - "fdes:0x%lx-0x%lx fres:0x%lx-0x%lx " - "ra_off:%d fp_off:%d\n", - sec->sframe_start, sec->sframe_end, sec->text_start, sec->text_end, - sec->fdes_start, fdes_end, sec->fres_start, sec->fres_end, - sec->ra_off, sec->fp_off); + dbg_sec("SEC: sframe:0x%lx-0x%lx text:0x%lx-0x%lx " + "fdes:0x%lx-0x%lx fres:0x%lx-0x%lx " + "ra_off:%d fp_off:%d\n", + sec->sframe_start, sec->sframe_end, sec->text_start, sec->text_end, + sec->fdes_start, fdes_end, sec->fres_start, sec->fres_end, + sec->ra_off, sec->fp_off); +} + +static inline void dbg_init(struct sframe_section *sec) +{ + struct mm_struct *mm =3D current->mm; + struct vm_area_struct *vma; + + guard(mmap_read_lock)(mm); + vma =3D vma_lookup(mm, sec->sframe_start); + if (!vma) + sec->filename =3D kstrdup("(vma gone???)", GFP_KERNEL); + else if (vma->vm_file) + sec->filename =3D kstrdup_quotable_file(vma->vm_file, GFP_KERNEL); + else if (vma->vm_ops && vma->vm_ops->name) + sec->filename =3D kstrdup(vma->vm_ops->name(vma), GFP_KERNEL); + else if (arch_vma_name(vma)) + sec->filename =3D kstrdup(arch_vma_name(vma), GFP_KERNEL); + else if (!vma->vm_mm) + sec->filename =3D kstrdup("(vdso)", GFP_KERNEL); + else + sec->filename =3D kstrdup("(anonymous)", GFP_KERNEL); +} + +static inline void dbg_free(struct sframe_section *sec) +{ + kfree(sec->filename); } =20 #else /* !CONFIG_DYNAMIC_DEBUG */ =20 #define dbg(args...) no_printk(args) +#define dbg_sec(args... ) no_printk(args) =20 static inline void dbg_print_header(struct sframe_section *sec) {} =20 +static inline void dbg_init(struct sframe_section *sec) {} +static inline void dbg_free(struct sframe_section *sec) {} + #endif /* !CONFIG_DYNAMIC_DEBUG */ =20 #endif /* _SFRAME_DEBUG_H */ --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63BDD22FDE8; Tue, 8 Jul 2025 02:12:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; cv=none; b=rxQvz7okaFDQ0mEZrHuoU3GpyQjbHYFUGtaj50XMdBQzGian7POBewt8CBzdLRkhkhWbegIUy2WVA1q0/MjLoUwDGVaiTD41JEo+HK/a0dXaafAGhkPfmebXduIIY4axyQhcuI7SZlPhZldTMOqhlZU7AW8L17v/z2u050laJOc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; c=relaxed/simple; bh=cQU/IOg2dV3IqPOdj6NyIdrtPpR/u8Ehsn+YFDVM0xo=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=fKKxfSrMr4Zc57P7qgbk3MJiWYnLf6pSZ9msYkPNovBnEgOPdryxB/PxpwPaXAjCCCaFhMQJyRL7dARQOWKdf1gdS1eEmZxOBBhkCvmlgqz2pSqGINYV38xCl/88QLddGSnJATaZ5fxbMXVHWzW5p9zXMNKok7gODai5QkXlTZo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fPA1tQIM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fPA1tQIM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD6B2C4CEE3; Tue, 8 Jul 2025 02:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940720; bh=cQU/IOg2dV3IqPOdj6NyIdrtPpR/u8Ehsn+YFDVM0xo=; h=Date:From:To:Cc:Subject:References:From; b=fPA1tQIMqWWWMvKLXkD89IR5zIbHTYWDwq4rE/Utz13qlxjhuZJOVyDMxCNP2Ofh9 +kfd035HAz/KpEbC/gvlo7meJNdQzzHiwZWXoSa+fmvqtvV6joMrBQ2IZH467W94LZ GGl8LjdbntSXY0QNidTBtRQhT8EWfAm+yW18KN17/MRuk/M68H6Q+/CStu7Fri3RH7 NfBKPIgH7zZcRIO3vq56hMU9wWzmgsQUVlIqGgN8dByrwNAp41oZFBPD7bQIMNDJL+ AG7vLjZO95vqu588voAnQXLEuYeGtx+6N6HkO6+OSSO9eHWPrOqcKRP716KuwUx+tE 6Sx+o0dIM61BQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoO-00000000DfW-0qoe; Mon, 07 Jul 2025 22:12:00 -0400 Message-ID: <20250708021200.058879671@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:25 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 10/12] unwind_user/sframe: Enable debugging in uaccess regions References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Objtool warns about calling pr_debug() from uaccess-enabled regions, and rightfully so. Add a dbg_sec_uaccess() macro which temporarily disables uaccess before doing the dynamic printk, and use that to add debug messages throughout the uaccess-enabled regions. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- kernel/unwind/sframe.c | 60 ++++++++++++++++++++++++++++-------- kernel/unwind/sframe_debug.h | 31 +++++++++++++++++++ 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 66d3ba3c8389..3972bce40fc7 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -53,12 +53,15 @@ static __always_inline int __read_fde(struct sframe_sec= tion *sec, sizeof(struct sframe_fde), Efault); =20 ip =3D sec->sframe_start + fde->start_addr; - if (ip < sec->text_start || ip > sec->text_end) + if (ip < sec->text_start || ip > sec->text_end) { + dbg_sec_uaccess("bad fde num %d\n", fde_num); return -EINVAL; + } =20 return 0; =20 Efault: + dbg_sec_uaccess("fde %d usercopy failed\n", fde_num); return -EFAULT; } =20 @@ -85,16 +88,22 @@ static __always_inline int __find_fde(struct sframe_sec= tion *sec, unsafe_get_user(func_off, (s32 __user *)mid, Efault); =20 if (ip_off >=3D func_off) { - if (func_off < func_off_low) + if (func_off < func_off_low) { + dbg_sec_uaccess("fde %u not sorted\n", + (unsigned int)(mid - first)); return -EFAULT; + } =20 func_off_low =3D func_off; =20 found =3D mid; low =3D mid + 1; } else { - if (func_off > func_off_high) + if (func_off > func_off_high) { + dbg_sec_uaccess("fde %u not sorted\n", + (unsigned int)(mid - first)); return -EFAULT; + } =20 func_off_high =3D func_off; =20 @@ -116,6 +125,7 @@ static __always_inline int __find_fde(struct sframe_sec= tion *sec, return 0; =20 Efault: + dbg_sec_uaccess("fde usercopy failed\n"); return -EFAULT; } =20 @@ -140,6 +150,8 @@ static __always_inline int __find_fde(struct sframe_sec= tion *sec, ____UNSAFE_GET_USER_INC(to, from, u_or_s##32, label); \ break; \ default: \ + dbg_sec_uaccess("%d: bad UNSAFE_GET_USER_INC size %u\n",\ + __LINE__, size); \ return -EFAULT; \ } \ }) @@ -174,24 +186,34 @@ static __always_inline int __read_fre(struct sframe_s= ection *sec, u8 info; =20 addr_size =3D fre_type_to_size(fre_type); - if (!addr_size) + if (!addr_size) { + dbg_sec_uaccess("bad addr_size in fde info %u\n", fde->info); return -EFAULT; + } =20 - if (fre_addr + addr_size + 1 > sec->fres_end) + if (fre_addr + addr_size + 1 > sec->fres_end) { + dbg_sec_uaccess("fre addr+info goes past end of subsection\n"); return -EFAULT; + } =20 UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault); - if (fde_type =3D=3D SFRAME_FDE_TYPE_PCINC && ip_off > fde->func_size) + if (fde_type =3D=3D SFRAME_FDE_TYPE_PCINC && ip_off > fde->func_size) { + dbg_sec_uaccess("fre starts past end of function: ip_off=3D0x%x, func_si= ze=3D0x%x\n", + ip_off, fde->func_size); return -EFAULT; + } =20 UNSAFE_GET_USER_INC(info, cur, 1, Efault); offset_count =3D SFRAME_FRE_OFFSET_COUNT(info); offset_size =3D offset_size_enum_to_size(SFRAME_FRE_OFFSET_SIZE(info)); - if (!offset_count || !offset_size) + if (!offset_count || !offset_size) { + dbg_sec_uaccess("zero offset_count or size in fre info %u\n",info); return -EFAULT; - - if (cur + (offset_count * offset_size) > sec->fres_end) + } + if (cur + (offset_count * offset_size) > sec->fres_end) { + dbg_sec_uaccess("fre goes past end of subsection\n"); return -EFAULT; + } =20 fre->size =3D addr_size + 1 + (offset_count * offset_size); =20 @@ -200,8 +222,10 @@ static __always_inline int __read_fre(struct sframe_se= ction *sec, =20 ra_off =3D sec->ra_off; if (!ra_off) { - if (!offset_count--) + if (!offset_count--) { + dbg_sec_uaccess("zero offset_count, can't find ra_off\n"); return -EFAULT; + } =20 UNSAFE_GET_USER_INC(ra_off, cur, offset_size, Efault); } @@ -212,8 +236,10 @@ static __always_inline int __read_fre(struct sframe_se= ction *sec, UNSAFE_GET_USER_INC(fp_off, cur, offset_size, Efault); } =20 - if (offset_count) + if (offset_count) { + dbg_sec_uaccess("non-zero offset_count after reading fre\n"); return -EFAULT; + } =20 fre->ip_off =3D ip_off; fre->cfa_off =3D cfa_off; @@ -224,6 +250,7 @@ static __always_inline int __read_fre(struct sframe_sec= tion *sec, return 0; =20 Efault: + dbg_sec_uaccess("fre usercopy failed\n"); return -EFAULT; } =20 @@ -257,13 +284,20 @@ static __always_inline int __find_fre(struct sframe_s= ection *sec, which =3D !which; =20 ret =3D __read_fre(sec, fde, fre_addr, fre); - if (ret) + if (ret) { + dbg_sec_uaccess("fde addr 0x%x: __read_fre(%u) failed\n", + fde->start_addr, i); + dbg_print_fde_uaccess(sec, fde); return ret; + } =20 fre_addr +=3D fre->size; =20 - if (prev_fre && fre->ip_off <=3D prev_fre->ip_off) + if (prev_fre && fre->ip_off <=3D prev_fre->ip_off) { + dbg_sec_uaccess("fde addr 0x%x: fre %u not sorted\n", + fde->start_addr, i); return -EFAULT; + } =20 if (fre->ip_off > ip_off) break; diff --git a/kernel/unwind/sframe_debug.h b/kernel/unwind/sframe_debug.h index 7794bf0bd78c..045e9c0b16c9 100644 --- a/kernel/unwind/sframe_debug.h +++ b/kernel/unwind/sframe_debug.h @@ -13,6 +13,26 @@ #define dbg_sec(fmt, ...) \ dbg("%s: " fmt, sec->filename, ##__VA_ARGS__) =20 +#define __dbg_sec_descriptor(fmt, ...) \ + __dynamic_pr_debug(&descriptor, "sframe: %s: " fmt, \ + sec->filename, ##__VA_ARGS__) + +/* + * To avoid breaking uaccess rules, temporarily disable uaccess + * before calling printk. + */ +#define dbg_sec_uaccess(fmt, ...) \ +({ \ + DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ + if (DYNAMIC_DEBUG_BRANCH(descriptor)) { \ + user_read_access_end(); \ + __dbg_sec_descriptor(fmt, ##__VA_ARGS__); \ + BUG_ON(!user_read_access_begin( \ + (void __user *)sec->sframe_start, \ + sec->sframe_end - sec->sframe_start)); \ + } \ +}) + static __always_inline void dbg_print_header(struct sframe_section *sec) { unsigned long fdes_end; @@ -27,6 +47,15 @@ static __always_inline void dbg_print_header(struct sfra= me_section *sec) sec->ra_off, sec->fp_off); } =20 +static __always_inline void dbg_print_fde_uaccess(struct sframe_section *s= ec, + struct sframe_fde *fde) +{ + dbg_sec_uaccess("FDE: start_addr:0x%x func_size:0x%x " + "fres_off:0x%x fres_num:%d info:%u rep_size:%u\n", + fde->start_addr, fde->func_size, + fde->fres_off, fde->fres_num, fde->info, fde->rep_size); +} + static inline void dbg_init(struct sframe_section *sec) { struct mm_struct *mm =3D current->mm; @@ -57,8 +86,10 @@ static inline void dbg_free(struct sframe_section *sec) =20 #define dbg(args...) no_printk(args) #define dbg_sec(args... ) no_printk(args) +#define dbg_sec_uaccess(args...) no_printk(args) =20 static inline void dbg_print_header(struct sframe_section *sec) {} +static inline void dbg_print_fde_uaccess(struct sframe_section *sec, struc= t sframe_fde *fde) {} =20 static inline void dbg_init(struct sframe_section *sec) {} static inline void dbg_free(struct sframe_section *sec) {} --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D3E9230BFF; Tue, 8 Jul 2025 02:12:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; cv=none; b=NSP8L3pFkQE60ybALlAaP/9Q0MLKFza8LFhCdom9Mr0+wTmJHRhZbe7WNxgR7MdBrBaA83Fxscgf9876gurLADLAhJSYwsyTEZjtv883mhEvKZvvb0xtqtKUEalEUR2WWHTmfV6XC/qhfXw2sO9qN8b89KkJEc1vGpieIuip2wU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; c=relaxed/simple; bh=Kp6RYb5t+RCZ7jokiwYGJB2GAw8QmJKJAuA8NhLPUp4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=Aa88Tw42C2GaJ/wlMiA0iLMTu0CE3pVvMh6cdAszzNEGpxuuy3DNZxKmHq6/OMd6Z6f6msTojme7xLHeAOTccZi2LZuHVh/6hsfnq5XwCEYnOpXioGfxB6xCpDr+n/a8s1ViqmzBLbSXukYVpwkxxMJCe2NnhP6NISLkMtoZZZw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VDI5dXgc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VDI5dXgc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CF36C4CEF7; Tue, 8 Jul 2025 02:12:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940720; bh=Kp6RYb5t+RCZ7jokiwYGJB2GAw8QmJKJAuA8NhLPUp4=; h=Date:From:To:Cc:Subject:References:From; b=VDI5dXgchyXngwF9gjq44ApKHJNunSERqJc01O+SEFBvL4wgcfHl5aAQvpGno46Z4 HyEGRq/ORld4q4ah2FTfk8pFeoqCXI+RH2YsIvg0S16AC44tgAuydlK9qCqdX5NFda lEr1uYaH9uLgSym5yp2jQaoJJST5xzEy63C08g2B7iiQ2Wzh8GFcthxAntlYsz9/HF PK5HeKkkH/WL2lw6nswDW7SM76bGe5sMuOMrWX1Bk/aCyQZSQdTD/finxbv/ScNmgu i2JOj2HCVVpH9cH9ELGLSq6qeJLXa1D/BXwxYhP4LGw4H6WEV5ycI2+qUTcjcZa52D d7ivtv1UiFa2A== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoO-00000000Dg2-1ZjL; Mon, 07 Jul 2025 22:12:00 -0400 Message-ID: <20250708021200.223446028@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:26 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 11/12] unwind_user/sframe: Add .sframe validation option References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Add a debug feature to validate all .sframe sections when first loading the file rather than on demand. Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- arch/Kconfig | 19 ++++++++++ kernel/unwind/sframe.c | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index 0c6056ef13de..86eec85cb898 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -450,6 +450,25 @@ config HAVE_UNWIND_USER_SFRAME bool select UNWIND_USER =20 +config SFRAME_VALIDATION + bool "Enable .sframe section debugging" + depends on HAVE_UNWIND_USER_SFRAME + depends on DYNAMIC_DEBUG + help + When adding an .sframe section for a task, validate the entire + section immediately rather than on demand. + + This is a debug feature which is helpful for rooting out .sframe + section issues. If the .sframe section is corrupt, it will fail to + load immediately, with more information provided in dynamic printks. + + This has a significant page cache footprint due to its reading of the + entire .sframe section for every loaded executable and shared + library. Also, it's done for all processes, even those which don't + get stack traced by the kernel. Not recommended for general use. + + If unsure, say N. + config HAVE_PERF_REGS bool help diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 3972bce40fc7..6159f072bdb6 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -353,6 +353,83 @@ int sframe_find(unsigned long ip, struct unwind_user_f= rame *frame) return ret; } =20 +#ifdef CONFIG_SFRAME_VALIDATION + +static __always_inline int __sframe_validate_section(struct sframe_section= *sec) +{ + unsigned long prev_ip =3D 0; + unsigned int i; + + for (i =3D 0; i < sec->num_fdes; i++) { + struct sframe_fre *fre, *prev_fre =3D NULL; + unsigned long ip, fre_addr; + struct sframe_fde fde; + struct sframe_fre fres[2]; + bool which =3D false; + unsigned int j; + int ret; + + ret =3D __read_fde(sec, i, &fde); + if (ret) + return ret; + + ip =3D sec->sframe_start + fde.start_addr; + if (ip <=3D prev_ip) { + dbg_sec_uaccess("fde %u not sorted\n", i); + return -EFAULT; + } + prev_ip =3D ip; + + fre_addr =3D sec->fres_start + fde.fres_off; + for (j =3D 0; j < fde.fres_num; j++) { + int ret; + + fre =3D which ? fres : fres + 1; + which =3D !which; + + ret =3D __read_fre(sec, &fde, fre_addr, fre); + if (ret) { + dbg_sec_uaccess("fde %u: __read_fre(%u) failed\n", i, j); + dbg_print_fde_uaccess(sec, &fde); + return ret; + } + + fre_addr +=3D fre->size; + + if (prev_fre && fre->ip_off <=3D prev_fre->ip_off) { + dbg_sec_uaccess("fde %u: fre %u not sorted\n", i, j); + return -EFAULT; + } + + prev_fre =3D fre; + } + } + + return 0; +} + +static int sframe_validate_section(struct sframe_section *sec) +{ + int ret; + + if (!user_read_access_begin((void __user *)sec->sframe_start, + sec->sframe_end - sec->sframe_start)) { + dbg_sec("section usercopy failed\n"); + return -EFAULT; + } + + ret =3D __sframe_validate_section(sec); + user_read_access_end(); + return ret; +} + +#else /* !CONFIG_SFRAME_VALIDATION */ + +static int sframe_validate_section(struct sframe_section *sec) { return 0;= } + +#endif /* !CONFIG_SFRAME_VALIDATION */ + + static void free_section(struct sframe_section *sec) { dbg_free(sec); @@ -461,6 +538,10 @@ int sframe_add_section(unsigned long sframe_start, uns= igned long sframe_end, goto err_free; } =20 + ret =3D sframe_validate_section(sec); + if (ret) + goto err_free; + ret =3D mtree_insert_range(sframe_mt, sec->text_start, sec->text_end, sec= , GFP_KERNEL); if (ret) { dbg_sec("mtree_insert_range failed: text=3D%lx-%lx\n", --=20 2.47.2 From nobody Tue Oct 7 18:21:07 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CDBF7234964; Tue, 8 Jul 2025 02:12:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; cv=none; b=kiR+1ENdikE5oB39djDZcVWLthYp8Ac48abnMtS8ZYC/yQ1uI+/4xxu+Bgx+vzZ3IbXRqZkrQhUmHiRDar4P53isCXW9kV2zfKjXbFD1aXjQIw0fw9SLDulphO0qu32ntEMGJaE4dvuhgqRTVSHTJ+00vfzk3wNFBd3YzQHZvjg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751940720; c=relaxed/simple; bh=/FbdkqgsRHQT3grN+rP3vo0JEynwNZBN/vKs+JQRgx0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=MZRKzQWoSDyEqXeXaKnmQYQ/7V7189LB07nFCKUQGV6SQbsjkICojHqUsSzPZ+KscjXqYXSY6yjDhatM3fC19TCXf8NXAHTDoEPNK97T6CjQdzdT9q7DFvqV+pbznSg7oTE8hCz2sB8puCYgOo1zRVfA+3TQMXybdgbGoeAAQg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DpdZyziQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DpdZyziQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5591BC4CEFF; Tue, 8 Jul 2025 02:12:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751940720; bh=/FbdkqgsRHQT3grN+rP3vo0JEynwNZBN/vKs+JQRgx0=; h=Date:From:To:Cc:Subject:References:From; b=DpdZyziQEjyLVkRSx5ewFYD3A/AwizLJSJax7xpONR6pAdGYkswEPqWnokSuqDrse 3lRvrvqUQeGT5/xb0rrXaSTSvTNaEr7Lb/2R+Sxi379blICo7a4OepBduQ+YaOOSFl rPg+mfXM/U4PCIGAw0HdaFwUc2MEvweBMpByJO8IIQiXrCVd+L0OrHULCXQmA5Qdxe GgoC4ZpC2gdlnjy1bYpqmHEA4WQHa4kYQL+0ofNMK/CU/aRP/SjyNa8WkhyiANIzAC dchZlqejRnT5E688anYppXDW5VVGKWx0oODz8xehltry2jSnaV5UgNwaEAPaUOTMGA 4cOxSlz4dujxw== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uYxoO-00000000DgX-2J09; Mon, 07 Jul 2025 22:12:00 -0400 Message-ID: <20250708021200.397301537@kernel.org> User-Agent: quilt/0.68 Date: Mon, 07 Jul 2025 22:11:27 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org, x86@kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Josh Poimboeuf , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton , Jens Axboe , Florian Weimer , Sam James Subject: [PATCH v8 12/12] unwind_user/sframe: Add prctl() interface for registering .sframe sections References: <20250708021115.894007410@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf The kernel doesn't have direct visibility to the ELF contents of shared libraries. Add some prctl() interfaces which allow glibc to tell the kernel where to find .sframe sections. [ This adds an interface for prctl() for testing loading of sframes for libraries. But this interface should really be a system call. This patch is for testing purposes only and should not be applied to mainline. ] Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) --- include/uapi/linux/prctl.h | 6 +++++- kernel/sys.c | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 43dec6eed559..c575cf7151b1 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -351,7 +351,7 @@ struct prctl_mm_map { * configuration. All bits may be locked via this call, including * undefined bits. */ -#define PR_LOCK_SHADOW_STACK_STATUS 76 +#define PR_LOCK_SHADOW_STACK_STATUS 76 =20 /* * Controls the mode of timer_create() for CRIU restore operations. @@ -371,4 +371,8 @@ struct prctl_mm_map { # define PR_FUTEX_HASH_GET_SLOTS 2 # define PR_FUTEX_HASH_GET_IMMUTABLE 3 =20 +/* SFRAME management */ +#define PR_ADD_SFRAME 79 +#define PR_REMOVE_SFRAME 80 + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index adc0de0aa364..cf788e66dc86 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -65,6 +65,7 @@ #include #include #include +#include =20 #include =20 @@ -2824,6 +2825,14 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, a= rg2, unsigned long, arg3, case PR_FUTEX_HASH: error =3D futex_hash_prctl(arg2, arg3, arg4); break; + case PR_ADD_SFRAME: + error =3D sframe_add_section(arg2, arg3, arg4, arg5); + break; + case PR_REMOVE_SFRAME: + if (arg3 || arg4 || arg5) + return -EINVAL; + error =3D sframe_remove_section(arg2); + break; default: trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5); error =3D -EINVAL; --=20 2.47.2