From: sashiko-bot@kernel.org
To: "Jens Remus" <jremus@linux.ibm.com>
Cc: "Alexander Gordeev" <agordeev@linux.ibm.com>,
"Christian Borntraeger" <borntraeger@linux.ibm.com>,
linux-s390@vger.kernel.org, "Heiko Carstens" <hca@linux.ibm.com>,
"Vasily Gorbik" <gor@linux.ibm.com>,
linux-trace-kernel@vger.kernel.org
Subject: Re: [RFC PATCH v1 08/25] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree
Date: Tue, 18 Aug 2026 15:08:48 +0000 [thread overview]
Message-ID: <20260818150849.293061F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260818144954.2320378-9-jremus@linux.ibm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] The `eh_frame_mt` maple tree is initialized without `MT_FLAGS_USE_RCU`, causing internal nodes to be synchronously freed, which crashes concurrent lockless readers.
- [High] fork() fails to inherit .eh_frame_hdr registrations, breaking unwinding for child processes.
- [High] A TOCTOU race condition in `eh_frame_remove_section` allows a double-free of one section and a memory leak of another.
- [High] An integer overflow in `table_end` calculation allows maliciously crafted `.eh_frame_hdr` sections to bypass bounds checking.
- [Low] Appending INIT_MM_EH_FRAME in init_mm causes a missing comma syntax error on multiple architectures.
--
--- Patch [8]: [RFC PATCH v1 08/25] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree ---
commit bd68e8b201de54350859df41e271e507dd497773
Author: Jens Remus <jremus@linux.ibm.com>
Subject: unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree
This commit associates .eh_frame_hdr sections with their mm by adding them to
a per-mm maple tree which is indexed by the corresponding text address
range. A single .eh_frame_hdr section can be associated with multiple
text ranges.
> diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h
> --- a/include/linux/eh_frame.h
> +++ b/include/linux/eh_frame.h
[ ... ]
> @@ -19,14 +24,27 @@ struct eh_frame_section {
> u8 binary_search_table_enc;
> };
>
> +#define INIT_MM_EH_FRAME .eh_frame_mt = MTREE_INIT(eh_frame_mt, 0),
[Severity: Critical]
Is the MT_FLAGS_USE_RCU flag required here?
Since readers are locklessly iterating the tree using mt_for_each() (which
relies on rcu_read_lock()), omitting MT_FLAGS_USE_RCU causes concurrent
mtree_erase() or mtree_insert_range() to synchronously free internal nodes via
kfree() instead of kfree_rcu(). Can this cause a use-after-free for the
concurrent readers?
> +extern void eh_frame_free_mm(struct mm_struct *mm);
> +
> extern int eh_frame_add_section(unsigned long eh_frame_hdr_start,
[ ... ]
> diff --git a/kernel/fork.c b/kernel/fork.c
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
[ ... ]
> @@ -1082,6 +1084,13 @@ static void mmap_init_lock(struct mm_struct *mm)
> #endif
> }
>
> +static void mm_init_eh_frame(struct mm_struct *mm)
> +{
> +#ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME
> + mt_init(&mm->eh_frame_mt);
[Severity: Critical]
Should this use mt_init_flags() with MT_FLAGS_USE_RCU?
Similar to the INIT_MM_EH_FRAME macro, initializing without RCU could lead to
a use-after-free if internal maple tree nodes are freed while lockless readers
are iterating.
[Severity: High]
Does fork() fail to inherit .eh_frame_hdr registrations?
A process that registers unwinding information and then calls fork() will have
its VMAs copied in dup_mmap(), but the child receives this empty maple tree
without any copied eh_frame_mt entries. Will this break stack unwinding for
the child process?
> +#endif
> +}
> +
> static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
[ ... ]
> diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
> --- a/kernel/unwind/eh_frame.c
> +++ b/kernel/unwind/eh_frame.c
[ ... ]
> +static int __eh_frame_remove_section(struct mm_struct *mm,
> + struct eh_frame_section *sec)
> +{
> + if (!mtree_erase(&mm->eh_frame_mt, sec->text_start)) {
> + dbg("mtree_erase failed: text=%lx\n", sec->text_start);
> + return -EINVAL;
> + }
> +
> + call_srcu(&eh_frame_srcu, &sec->rcu, eh_frame_free_srcu);
> +
> + return 0;
> +}
> +
> int eh_frame_remove_section(unsigned long eh_frame_hdr_start)
> {
> - return -ENOSYS;
> + struct mm_struct *mm = current->mm;
> + struct eh_frame_section *sec;
> + unsigned long index = 0;
> + bool found = false;
> + int ret = 0;
> +
> + guard(srcu)(&eh_frame_srcu);
> +
> + mt_for_each(&mm->eh_frame_mt, sec, index, ULONG_MAX) {
> + if (sec->eh_frame_hdr_start == eh_frame_hdr_start) {
> + found = true;
> + ret |= __eh_frame_remove_section(mm, sec);
> + }
> + }
[Severity: High]
Can this mtree_erase() and call_srcu() sequence race with another thread and
cause a double-free?
If Thread A locklessly iterates and finds sec1 in mt_for_each(), and Thread B
concurrently removes sec1, Thread C could map a new section sec2 at the same
text_start address.
When Thread A calls __eh_frame_remove_section(mm, sec1), mtree_erase() would
successfully remove and return sec2. However, Thread A then passes the
original sec1 pointer to call_srcu(), double-freeing sec1 and leaking sec2.
[ ... ]
> diff --git a/mm/init-mm.c b/mm/init-mm.c
> --- a/mm/init-mm.c
> +++ b/mm/init-mm.c
> @@ -48,6 +49,7 @@ struct mm_struct init_mm = {
> #endif
> .flexible_array = MM_STRUCT_FLEXIBLE_ARRAY_INIT,
> INIT_MM_CONTEXT(init_mm)
> + INIT_MM_EH_FRAME
> };
[Severity: Low]
Does appending INIT_MM_EH_FRAME here cause a missing comma syntax error on
some architectures?
While x86's INIT_MM_CONTEXT was updated to include a trailing comma in this
patch, other architectures (like UML or PowerPC Book3s 32-bit) may lack this
trailing comma in their INIT_MM_CONTEXT definitions, breaking the build.
In a related function, eh_frame_read_header() contains a potential overflow:
kernel/unwind/eh_frame.c:eh_frame_read_header() {
...
table_end = table_start + fde_count * entry_size;
if (table_end > sec->eh_frame_hdr_end)
return -EINVAL;
...
}
[Severity: High]
Can this arithmetic multiplication overflow and bypass the bounds check?
If a malicious .eh_frame_hdr provides an artificially large fde_count,
fde_count * entry_size could overflow the unsigned long capacity, wrapping
around to a small value. This would bypass the bounds check and allow
out-of-bounds reads during later unwinding binary searches.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260818144954.2320378-1-jremus@linux.ibm.com?part=8
next prev parent reply other threads:[~2026-08-18 15:08 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 14:49 [RFC PATCH v1 00/25] unwind_user: Implement .eh_frame handling Jens Remus
2026-08-18 14:49 ` [RFC PATCH v1 01/25] unwind_user: Add generic and arch-specific headers to MAINTAINERS Jens Remus
2026-08-18 14:49 ` [RFC PATCH v1 02/25] unwind_user: Stop when reaching an outermost frame Jens Remus
2026-08-18 14:56 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 03/25] unwind_user: Enable archs that pass RA in a register Jens Remus
2026-08-18 14:58 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 04/25] unwind_user: Flexible FP/RA recovery rules Jens Remus
2026-08-18 14:58 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 05/25] unwind_user: Flexible CFA " Jens Remus
2026-08-18 14:57 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 06/25] unwind_user: Enable archs that define CFA = SP_callsite + offset Jens Remus
2026-08-18 14:57 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 07/25] unwind_user/eh_frame: Add support for reading .eh_frame_hdr section Jens Remus
2026-08-18 15:02 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 08/25] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree Jens Remus
2026-08-18 15:08 ` sashiko-bot [this message]
2026-08-18 14:49 ` [RFC PATCH v1 09/25] unwind_user/eh_frame: Add support for reading .eh_frame section Jens Remus
2026-08-18 15:05 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 10/25] unwind_user/eh_frame: Detect .eh_frame_hdr sections in executables Jens Remus
2026-08-18 15:18 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 11/25] unwind_user/eh_frame: Wire up unwind_user to eh_frame Jens Remus
2026-08-18 15:09 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 12/25] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption Jens Remus
2026-08-18 15:10 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 13/25] unwind_user/eh_frame: Show file name in debug output Jens Remus
2026-08-18 15:00 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 14/25] unwind_user/eh_frame: Add .eh_frame[_hdr] validation option Jens Remus
2026-08-18 15:08 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 15/25] unwind_user/eh_frame: Duplicate registered .eh_frame[_hdr] section data on clone/fork Jens Remus
2026-08-18 15:11 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 16/25] unwind_user/eh_frame: Add linear .eh_frame search fallback Jens Remus
2026-08-18 15:06 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 17/25] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size Jens Remus
2026-08-18 15:04 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 18/25] unwind_user/eh_frame: Add support for DWARF expressions Jens Remus
2026-08-18 15:13 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 19/25] x86/uaccess: Add unsafe_copy_from_user() implementation Jens Remus
2026-08-18 15:08 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 20/25] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86 Jens Remus
2026-08-18 15:04 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 21/25] unwind_user/eh_frame/x86: Handle PLT expressions Jens Remus
2026-08-18 15:10 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 22/25] unwind_user/eh_frame/x86: Handle DRAP expressions Jens Remus
2026-08-18 15:10 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 23/25] s390/ptrace: Provide frame_pointer() Jens Remus
2026-08-18 15:06 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 24/25] unwind_user/eh_frame/s390: Enable eh_frame unwinding on s390 Jens Remus
2026-08-18 15:15 ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 25/25] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections Jens Remus
2026-08-18 15:17 ` sashiko-bot
2026-08-18 17:21 ` [RFC PATCH v1 00/25] unwind_user: Implement .eh_frame handling Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818150849.293061F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=jremus@linux.ibm.com \
--cc=linux-s390@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.