From nobody Tue Oct 7 11:55:13 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (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 1E16C271462 for ; Thu, 10 Jul 2025 16:43:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165790; cv=none; b=lIV910QQSt3fTaIedd+8xNuq2UkDmosl4o28UaSnlSxOdQdkytXiH6balZ/l0vg03Q3077kNHedRIs5IWZvjzXZTdYLggjstsMe+Cw9/Djow8aWekHrV1D/SQ9boXuiV/glSnitGQET6XMq7M2aQnc4bCCzBXh/wrftNb/nZB4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165790; c=relaxed/simple; bh=65F4kOGhiJ+MurE1/h28LSvsnry0cAOnSkAN08hocA4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZwHWqNdfS5OpYZhZrEDigEpgHg56CDrQsnbBIKme+TV/agDkbjEtcVO1GPyOeo5gjsMpeRN8mOeJjjDE9oagrF+ub2UA1D5ArP4bFVlRChuWGtmWa4Ov4IadElck8iauXN/AkGO0gcbg7hwNVMHaHNJJHqIv2zJBBTrTCkSWIJU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=O2AJqeo3; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="O2AJqeo3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752165787; bh=65F4kOGhiJ+MurE1/h28LSvsnry0cAOnSkAN08hocA4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=O2AJqeo3BIc/fPPXnp0gE1ePdcHLU3acFeemGRDRiPKEKqfl5rvk21EkzYBw6n6Eb YzF0wI85FiyAluTWr1MWj1eedMPLnhLlxmomKkLgxV/6ElRvT/5b4TE9DcP7MtE2gh fWgZavjThF567TPrffg7qZRsRvCiaC23BZ4UpW+aoPzEQ7nCgdz0bbpA0pe9VPeXy9 n+eQ6b79njS9jEKEtwU5YnblP1BSTq3lxGZxokEMQpoQQhwjgJjrRgu8ecsoW+MyQ1 5p183agKOvZJMuTYaU24UddzGTLlkehm64Hlk/Nn/gx9NCnDs5lVgWVijaIasa+EW+ g9DSGjqhAYTCw== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bdLHt57pgzpqp; Thu, 10 Jul 2025 12:43:06 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , 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 Subject: [RFC PATCH v2 1/3] unwind_user: Fix userspace unwind iterator 32-bit compat handling Date: Thu, 10 Jul 2025 12:42:56 -0400 Message-ID: <20250710164301.3094-2-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> References: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> 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" Refactor the stack unwind iterator to clean the overall design and fix 32-bit compat corner-cases that arise due to confusion over the semantic of the struct unwind_user_state type field. Observed Issue =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Before this refactor, the struct unwind_user_state type field identifies: - Whether sframe is available in the current process, for at least portions of the address space, - Whether frame pointers should be used for stack walk, - Whether frame pointers should be used for stack walk in a 32-bit compat process. It would be natural for the unwind iterator caller to expect the "state->type" to contain the type of stack walk operation performed for the most recent unwind iteration (unwind_user_next()), but it actually acts as an internal cache and is unrelated to the current iteration, which makes this field confusing. It is not only confusing to the caller, but also to the implementation of unwind_user_next(). Is has the following drawbacks: - A 32-bit compat process will favor using frame pointers rather than sframe for its next unwind iterator, which is an unexpected priority order because sframe is more accurate than frame pointers when available. - Because the "UNWIND_USER_TYPE_SFRAME" state type is unaware of 32-bit compat, handling of sframe would be broken on 32-bit compat because compat_fp_state() would return false, thus expecting 64-bit unsigned long types. Cause =3D=3D=3D=3D=3D Associating a semantic to a single enumeration field that consists of: - many orthogonal properties, without listing all those properties (sframe vs frame pointer, compat vs non-compat) within each of the enumeration labels, - an implicit priority, leads to confusion in the unwind iterator implementation. Solution =3D=3D=3D=3D=3D=3D=3D=3D Split this type field into two fields: - A "current_type" field, which can be queried by the iterator caller and by architecture code to learn which method is used for the current unwind iteration, - An "available_types" field, which is a bitmask of available user types. It is used internally by the iterator implementation. Remove the "UNWIND_USER_TYPE_COMPAT_FP" label from the unwind types, since it is now implicitly taken into account by the unwind_compat_mode() check. This approach will also make it easier to introduce new unwind types in the future, such as an unwinder for JIT code. Rename in_compat_mode to unwind_compat_mode to remove confusion between the pre-existing in_compat_syscall() macro (which returns true for both ia32 and x32) and unwind_compat_mode() which only returns true for ia32. Known Drawbacks =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D None. [ This is based on linux-trace unwind/sframe ] Fixes: 1abc29eeca39 ("unwind_user/sframe: Wire up unwind_user to sframe") Fixes: ce8d69a1a578 ("unwind_user/x86: Enable compat mode frame pointer unw= inding on x86") Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- arch/x86/include/asm/unwind_user.h | 6 +- arch/x86/kernel/stacktrace.c | 2 +- include/asm-generic/unwind_user.h | 4 + include/linux/unwind_user.h | 9 -- include/linux/unwind_user_types.h | 25 ++++-- kernel/unwind/user.c | 139 +++++++++++++++++------------ 6 files changed, 110 insertions(+), 75 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index 19634a73612d..1b32491f28a5 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -10,6 +10,8 @@ .fp_off =3D (s32)sizeof(long) * -2, \ .use_fp =3D true, =20 +#define unwind_compat_mode(regs) (!user_64bit_mode(regs)) + #ifdef CONFIG_IA32_EMULATION =20 #define ARCH_INIT_USER_COMPAT_FP_FRAME \ @@ -18,14 +20,12 @@ .fp_off =3D (s32)sizeof(u32) * -2, \ .use_fp =3D true, =20 -#define in_compat_mode(regs) !user_64bit_mode(regs) - void arch_unwind_user_init(struct unwind_user_state *state, struct pt_regs *regs); =20 static inline void arch_unwind_user_next(struct unwind_user_state *state) { - if (state->type !=3D UNWIND_USER_TYPE_COMPAT_FP) + if (!unwind_compat_mode(task_pt_regs(current))) return; =20 state->ip +=3D state->arch.cs_base; diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index 8ef9d8c71df9..3e970162fc0f 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c @@ -137,7 +137,7 @@ void arch_unwind_user_init(struct unwind_user_state *st= ate, { unsigned long cs_base, ss_base; =20 - if (state->type !=3D UNWIND_USER_TYPE_COMPAT_FP) + if (!unwind_compat_mode(regs)) return; =20 cs_base =3D insn_get_seg_base(regs, INAT_SEG_REG_CS); diff --git a/include/asm-generic/unwind_user.h b/include/asm-generic/unwind= _user.h index b8882b909944..f9d7603670cd 100644 --- a/include/asm-generic/unwind_user.h +++ b/include/asm-generic/unwind_user.h @@ -2,4 +2,8 @@ #ifndef _ASM_GENERIC_UNWIND_USER_H #define _ASM_GENERIC_UNWIND_USER_H =20 +#ifndef unwind_compat_mode +#define unwind_compat_mode(regs) false +#endif + #endif /* _ASM_GENERIC_UNWIND_USER_H */ diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 8a4af0214ecb..0308adb349fc 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -5,15 +5,6 @@ #include #include =20 -#ifndef ARCH_INIT_USER_FP_FRAME - #define ARCH_INIT_USER_FP_FRAME -#endif - -#ifndef ARCH_INIT_USER_COMPAT_FP_FRAME - #define ARCH_INIT_USER_COMPAT_FP_FRAME - #define in_compat_mode(regs) false -#endif - /* * If an architecture needs to initialize the state for a specific * reason, for example, it may need to do something different diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 4d50476e950e..41ea44c5ce5c 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -9,11 +9,23 @@ struct arch_unwind_user_state {}; #endif =20 + +/* + * Unwind types, listed in priority order: lower numbers are attempted fir= st if + * available. + */ +enum unwind_user_type_bits { + UNWIND_USER_TYPE_SFRAME_BIT =3D 0, + UNWIND_USER_TYPE_FP_BIT =3D 1, + + _NR_UNWIND_USER_TYPE_BITS, +}; + enum unwind_user_type { - UNWIND_USER_TYPE_NONE, - UNWIND_USER_TYPE_FP, - UNWIND_USER_TYPE_COMPAT_FP, - UNWIND_USER_TYPE_SFRAME, + /* Type "none" for the start of stack walk iteration. */ + UNWIND_USER_TYPE_NONE =3D 0, + UNWIND_USER_TYPE_SFRAME =3D (1U << UNWIND_USER_TYPE_SFRAME_BIT), + UNWIND_USER_TYPE_FP =3D (1U << UNWIND_USER_TYPE_FP_BIT), }; =20 struct unwind_stacktrace { @@ -33,7 +45,10 @@ struct unwind_user_state { unsigned long sp; unsigned long fp; struct arch_unwind_user_state arch; - enum unwind_user_type type; + /* Unwind time used for the most recent unwind traversal iteration. */ + enum unwind_user_type current_type; + /* Unwind types available in the current context. Bitmask of enum unwind_= user_type. */ + unsigned int available_types; bool done; }; =20 diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 6e7ca9f1293a..18d83efc876e 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -13,70 +13,43 @@ static struct unwind_user_frame fp_frame =3D { ARCH_INIT_USER_FP_FRAME }; =20 +#ifdef CONFIG_HAVE_UNWIND_USER_COMPAT_FP static struct unwind_user_frame compat_fp_frame =3D { ARCH_INIT_USER_COMPAT_FP_FRAME }; +#endif =20 -static inline bool fp_state(struct unwind_user_state *state) +static struct unwind_user_frame *get_fp_frame(struct pt_regs *regs) { - return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP) && - state->type =3D=3D UNWIND_USER_TYPE_FP; +#ifdef CONFIG_HAVE_UNWIND_USER_COMPAT_FP + if (unwind_compat_mode(regs)) + return &compat_fp_frame; +#endif + return &fp_frame; } =20 #define for_each_user_frame(state) \ for (unwind_user_start(state); !(state)->done; unwind_user_next(state)) =20 -static inline bool compat_fp_state(struct unwind_user_state *state) -{ - return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_COMPAT_FP) && - state->type =3D=3D UNWIND_USER_TYPE_COMPAT_FP; -} - -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) \ +#define unwind_get_user_long(to, from, regs) \ ({ \ int __ret; \ - if (compat_fp_state(state)) \ + if (unwind_compat_mode(regs)) \ __ret =3D get_user(to, (u32 __user *)(from)); \ else \ __ret =3D get_user(to, (unsigned long __user *)(from)); \ __ret; \ }) =20 -static int unwind_user_next(struct unwind_user_state *state) +static int unwind_user_next_common(struct unwind_user_state *state, struct= unwind_user_frame *frame, + struct pt_regs *regs) { - struct unwind_user_frame *frame; - struct unwind_user_frame _frame; - unsigned long cfa =3D 0, fp, ra =3D 0; + unsigned long cfa, fp, ra =3D 0; unsigned int shift; =20 - if (state->done) - return -EINVAL; - - if (compat_fp_state(state)) { - frame =3D &compat_fp_frame; - } 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 { - goto done; - } - if (frame->use_fp) { if (state->fp < state->sp) - goto done; + return -EINVAL; cfa =3D state->fp; } else { cfa =3D state->sp; @@ -87,30 +60,86 @@ static int unwind_user_next(struct unwind_user_state *s= tate) =20 /* stack going in wrong direction? */ if (cfa <=3D state->sp) - goto done; + return -EINVAL; =20 /* Make sure that the address is word aligned */ - shift =3D sizeof(long) =3D=3D 4 || compat_fp_state(state) ? 2 : 3; + shift =3D (sizeof(long) =3D=3D 4 || unwind_compat_mode(regs)) ? 2 : 3; if ((cfa + frame->ra_off) & ((1 << shift) - 1)) - goto done; + return -EINVAL; =20 /* Find the Return Address (RA) */ - if (unwind_get_user_long(ra, cfa + frame->ra_off, state)) - goto done; + if (unwind_get_user_long(ra, cfa + frame->ra_off, regs)) + return -EINVAL; =20 - if (frame->fp_off && unwind_get_user_long(fp, cfa + frame->fp_off, state)) - goto done; + if (frame->fp_off && unwind_get_user_long(fp, cfa + frame->fp_off, regs)) + return -EINVAL; =20 state->ip =3D ra; state->sp =3D cfa; if (frame->fp_off) state->fp =3D fp; + return 0; +} =20 - arch_unwind_user_next(state); +static int unwind_user_next_sframe(struct unwind_user_state *state) +{ + struct unwind_user_frame _frame, *frame; + + /* sframe expects the frame to be local storage */ + frame =3D &_frame; + if (sframe_find(state->ip, frame)) + return -ENOENT; + return unwind_user_next_common(state, frame, task_pt_regs(current)); +} + +static int unwind_user_next_fp(struct unwind_user_state *state) +{ + struct pt_regs *regs =3D task_pt_regs(current); + + return unwind_user_next_common(state, get_fp_frame(regs), regs); +} + +static int unwind_user_next(struct unwind_user_state *state) +{ + unsigned long iter_mask =3D state->available_types; + unsigned int bit; =20 + if (state->done) + return -EINVAL; + + for_each_set_bit(bit, &iter_mask, _NR_UNWIND_USER_TYPE_BITS) { + enum unwind_user_type type =3D 1U << bit; + + state->current_type =3D type; + switch (type) { + case UNWIND_USER_TYPE_SFRAME: + switch (unwind_user_next_sframe(state)) { + case 0: + goto end; + case -ENOENT: + continue; /* Try next method. */ + default: + goto done; + } + case UNWIND_USER_TYPE_FP: + if (!unwind_user_next_fp(state)) + goto end; + else + goto done; + case UNWIND_USER_TYPE_NONE: + break; + } + } + + /* No successful unwind method. */ + goto done; + +end: + arch_unwind_user_next(state); return 0; =20 done: + state->current_type =3D UNWIND_USER_TYPE_NONE; state->done =3D true; return -EINVAL; } @@ -126,14 +155,10 @@ static int unwind_user_start(struct unwind_user_state= *state) return -EINVAL; } =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 - state->type =3D UNWIND_USER_TYPE_NONE; + if (current_has_sframe()) + state->available_types |=3D UNWIND_USER_TYPE_SFRAME; + if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) + state->available_types |=3D UNWIND_USER_TYPE_FP; =20 state->ip =3D instruction_pointer(regs); state->sp =3D user_stack_pointer(regs); --=20 2.43.0 From nobody Tue Oct 7 11:55:13 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (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 52AF327817F for ; Thu, 10 Jul 2025 16:43:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165789; cv=none; b=AjeyoQ0zy5iNpdeiriHHyuCwNfQ67CSl0HItxFWA/eedNljUU7Ee8RUR0s79jo2a+e9jcNuYIDEX+0VZbN3OLWZDr3fUeM9YKt/pK7eZyphj5KaplimE6LfBu0ax0c16nGnjiODr3WpRG6JZi8a6AU4j+B1GGVqS33JI/j3Z8a4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165789; c=relaxed/simple; bh=FsUOQ6i8OQS2NzfcLZRerrJnttdZzoVrOdkx6MT1NUE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ezZ04HQHFGOE4jteGoBX8xH0kiSU07COcURXMy8wNt7We2XLN50m66j7Dc43Q58x2aMAScVKTXFOx7wuBwODa17AXj5QKD5GdkH6v13R0WY9zKADfRB939LAjT+O5dnSbGh9QzD97peWaV/81zJAGiQCmqU6AqntdruOa4I9fRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=WIFrePVe; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="WIFrePVe" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752165787; bh=FsUOQ6i8OQS2NzfcLZRerrJnttdZzoVrOdkx6MT1NUE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WIFrePVeBZa7/vcr23ZeyToWp1Vkut0oGDnKU4EF66JlqUEp/9lSKty2sBHlutOGG fUU/vV4deSTzBdpNTRhwUejLz05fpJrVa4vV+mzVZRIh15YkQvHcf6zHofttdek3NC lv2II8G9Zk32uZjQrkRSDmkSXk23r1yYuP+ZAhojfithvHl5dByEKNGLBK9g4u0Uhm f01pvi8QraDWU9H2NWR5MWvAd8ECc07dJKzNUsK3xyjiOxWTFB391scoO66MhsHaWX aN38DDc90DbpeHH4LIC19EOz37oCI0xUTaRJvwjNe0Srr1AgxozR9eSUstYxdYjn/B etQhtQVWLBPdQ== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bdLHv13c9zq8r; Thu, 10 Jul 2025 12:43:07 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , 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 Subject: [RFC PATCH v2 2/3] unwind: Export unwind_user symbol to GPL modules Date: Thu, 10 Jul 2025 12:42:57 -0400 Message-ID: <20250710164301.3094-3-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> References: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> 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" Allow the unwind_user symbol to be used by GPL modules, for instance LTTng. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- kernel/unwind/user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 18d83efc876e..7d7dfb8178d0 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -189,3 +189,4 @@ int unwind_user(struct unwind_stacktrace *trace, unsign= ed int max_entries) =20 return 0; } +EXPORT_SYMBOL_GPL(unwind_user); --=20 2.43.0 From nobody Tue Oct 7 11:55:13 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (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 B5040280A3B for ; Thu, 10 Jul 2025 16:43:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165790; cv=none; b=FR3AHnmqF8bQBDSYx/whnW0qhy4N0DXGkAGLZ42Jld62CFj6TEPldFs+XsMIWSN/HocbjfBAuRlWvULkq1PrZEMgp4XU3zokAXXO1QGqqK7J2u4OdI9LyGaokYv9SsYDZitW7fpUeEwbzhffhgq/B2nXJ33fuW/A75LZNaKEbIM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752165790; c=relaxed/simple; bh=iauZL9jmjufsByEqjLynOS/a/I/93HipMuGHw4CkAUk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G2AzFjzJcniWE4eh7aT0qV2sBOHdjPNIMK0Cot+/LTy04cvWY4gD7Y4qDpMn8ReUHscEBYAaou0y44Ppyov+ZHurONUC8UqWEDInLCrKCNW6NrN9FuQaUucT19e/XtXdTxjL5g8g8Jia117bExy++AtTi5P9g3IJ+pFUyjn6pN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=W2FEa5gW; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="W2FEa5gW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752165787; bh=iauZL9jmjufsByEqjLynOS/a/I/93HipMuGHw4CkAUk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W2FEa5gWKrWfLNFrclgLeBD1+6NtU9tpTe6XPzm1LsN4QxMfQg8tAsJCKPdQP9RvY SK1jd44Qn3Odt+TsFhLZzFmsXlhesFiZ7rx359D5ogGqHpRgltrd/TxNRr038bg0UO EbZzRrGNbmcudCowsvXTs54QAj78PNFKuWebGUlyY1YdtN3M7ZpM5XHr+HawyWHoio RJGRKovFvIvDwdbodtBHASRvAb3NJe6imnyDLWF70y0u/oc5qHRc8kcme2nmckNvbu umB3WZR6/R6GVH93HhWfAqlbBbY9sOr2G6rcZzi1zGljJdDmJ+OoD4uJ25rMPbTtHE 0doI4YoSOzKgw== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bdLHv40qpzq8s; Thu, 10 Jul 2025 12:43:07 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , 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 Subject: [RFC PATCH v2 3/3] unwind deferred: Introduce unwind_user_trace_cached Date: Thu, 10 Jul 2025 12:42:58 -0400 Message-ID: <20250710164301.3094-4-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> References: <20250710164301.3094-1-mathieu.desnoyers@efficios.com> 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" Introduce unwind_user_trace_cached which copies the stack trace if it was previously stored into the cache since the last reset of the cache. The expected use-case is sampling a stack trace from a faultable context at system call entry (coping it into the cache), and then copying the stack trace from the cache from non-faultable context to a ring buffer. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- include/linux/unwind_deferred.h | 2 ++ kernel/unwind/deferred.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/unwind_deferred.h b/include/linux/unwind_deferre= d.h index a9d5b100d6b2..ddc985ba982a 100644 --- a/include/linux/unwind_deferred.h +++ b/include/linux/unwind_deferred.h @@ -34,6 +34,7 @@ void unwind_task_init(struct task_struct *task); void unwind_task_free(struct task_struct *task); =20 int unwind_user_faultable(struct unwind_stacktrace *trace); +int unwind_user_trace_cached(struct unwind_stacktrace *trace); =20 int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func); int unwind_deferred_request(struct unwind_work *work, u64 *cookie); @@ -67,6 +68,7 @@ static inline void unwind_task_init(struct task_struct *t= ask) {} static inline void unwind_task_free(struct task_struct *task) {} =20 static inline int unwind_user_faultable(struct unwind_stacktrace *trace) {= return -ENOSYS; } +static inline int unwind_user_trace_cached(struct unwind_stacktrace *trace= ) { return -ENOSYS; } static inline int unwind_deferred_init(struct unwind_work *work, unwind_ca= llback_t func) { return -ENOSYS; } static inline int unwind_deferred_request(struct unwind_work *work, u64 *t= imestamp) { return -ENOSYS; } static inline void unwind_deferred_cancel(struct unwind_work *work) {} diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c index 039e12700d49..02ab1d2afc21 100644 --- a/kernel/unwind/deferred.c +++ b/kernel/unwind/deferred.c @@ -145,6 +145,37 @@ int unwind_user_faultable(struct unwind_stacktrace *tr= ace) =20 return 0; } +EXPORT_SYMBOL_GPL(unwind_user_faultable); + +/** + * unwind_user_trace_cached - Copy user stack trace from cache + * @trace: The descriptor that will store the user stacktrace + * + * Copy user stack trace from cache if the cache was populated by + * unwind_user_faultable prior to this call. The returned trace + * entries are only valid until the cache is reset. + * + * Return: 0 on success and negative on error + * On success @trace will contain the user space stacktrace + */ +int unwind_user_trace_cached(struct unwind_stacktrace *trace) +{ + struct unwind_task_info *info =3D ¤t->unwind_info; + struct unwind_cache *cache; + + if (!current->mm) + return -EINVAL; + + cache =3D info->cache; + if (!cache || !cache->nr_entries) + return -ENOENT; + + trace->nr =3D cache->nr_entries; + trace->entries =3D cache->entries; + + return 0; +} +EXPORT_SYMBOL_GPL(unwind_user_trace_cached); =20 static void process_unwind_deferred(struct task_struct *task) { --=20 2.43.0