From: sashiko-bot@kernel.org
To: "Jens Remus" <jremus@linux.ibm.com>
Cc: "Alexander Gordeev" <agordeev@linux.ibm.com>,
"Heiko Carstens" <hca@linux.ibm.com>,
"Vasily Gorbik" <gor@linux.ibm.com>,
linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org,
"Christian Borntraeger" <borntraeger@linux.ibm.com>
Subject: Re: [RFC PATCH v2 12/24] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption
Date: Fri, 21 Aug 2026 20:18:20 +0000 [thread overview]
Message-ID: <20260821201820.81B8D1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260821195259.2688377-13-jremus@linux.ibm.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] A Time-of-Check to Time-of-Use (TOCTOU) race condition allows the kernel to erroneously unregister a valid, newly loaded .eh_frame section due to address reuse.
- [High] The unwinder conflates actual memory corruption with kernel-imposed safety limits, permanently disabling unwinding for valid libraries.
Pre-existing issues:
- [Critical] Unchecked error from mas_erase() leads to freeing a maple tree section while it remains active in the tree, causing a Use-After-Free (UAF).
- [High] Lock drop and reacquire inside mas_erase() during mas_for_each() iteration causes a TOCTOU race and memory leak.
--
--- Patch [12]: [RFC PATCH v2 12/24] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption ---
commit 14251b7471659003e9517d814ad704b284ed18df
Author: Jens Remus <jremus@linux.ibm.com>
unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption
This commit adds logic to unregister .eh_frame or .eh_frame_hdr sections on
demand when corruption is detected during lookup. This prevents repeated
attempts to parse bad unwind sections by removing them immediately upon an
error return.
> diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
> index 21f40805b417f..327849ea4a692 100644
> --- a/kernel/unwind/eh_frame.c
> +++ b/kernel/unwind/eh_frame.c
> @@ -1202,6 +1202,15 @@ int eh_frame_find(unsigned long ip, struct unwind_user_frame *frame)
> if (!ret)
> ret = __find_frame_row(sec, &fde, ip, frame);
>
> + /*
> + * Unregister .eh_frame[_hdr] in case of an error,
> + * e.g. EINVAL (corrupted) or EFAULT (inaccessible).
> + * Keep if ENOENT (not found) or EOPNOTSUPP (unsupported CFI).
> + */
> + if (ret && (ret != -ENOENT && ret != -EOPNOTSUPP))
> + if (eh_frame_remove_section(sec->eh_frame_hdr_start))
> + dbg("eh_frame_remove_section() failed\n");
> +
[Severity: High]
Does this introduce a race condition with memory unmapping and mapping?
If a thread is delayed after retrieving sec in eh_frame_find(), another
thread could unmap the library and map a new library at the exact same
virtual address, registering it with the same eh_frame_hdr_start. When the
first thread resumes and fails to parse against the new memory, passing the
virtual address sec->eh_frame_hdr_start to eh_frame_remove_section() seems
like it would unintentionally remove the newly loaded, valid library's
section.
[Severity: High]
Is it safe to assume -EINVAL always means corruption?
Looking at __do_cfi_program(), it also returns -EINVAL when kernel limits
are hit, such as exceeding EH_FRAME_CFI_INSN_LIMIT or
EH_FRAME_MAX_CODE_ALIGN.
If a valid library simply has a complex function that hits these limits,
wouldn't this code globally and permanently disable unwinding for it by
removing its section?
[Severity: High]
This is a pre-existing issue, but looking at eh_frame_remove_section()
which is called here, is there a memory leak if mas_erase() drops the lock?
eh_frame_remove_section() holds mtree_lock and iterates via mas_for_each().
It calls __eh_frame_remove_section(), which calls mas_erase().
If mas_erase() needs to allocate memory via mas_nomem(mas, GFP_KERNEL), it
can drop the tree lock. If a concurrent thread inserts a new section
covering the same range during this unlocked window, mas_erase() retries,
erases the new section, and returns it.
__eh_frame_remove_section() then sees the returned entry doesn't match sec,
returns -EINVAL, and skips call_srcu(), potentially leaking the new section.
[Severity: Critical]
This is a pre-existing issue, but looking at __eh_frame_remove_section()
called by eh_frame_remove_section(), can a memory allocation failure lead
to a use-after-free?
If mas_nomem() fails to allocate memory during mas_erase(), it sets an
error state and aborts without removing the node, but still returns the
original sec:
__eh_frame_remove_section() {
...
if (mas_erase(mas) != sec) {
return -EINVAL;
}
call_srcu(&eh_frame_srcu, &sec->rcu, eh_frame_free_srcu);
...
}
Because __eh_frame_remove_section() only checks if the return value does
not equal sec, it misses the error state completely. It then calls
call_srcu() to free the section while the node remains active in the maple
tree. Could subsequent calls to eh_frame_find() load and access this freed
memory?
> return ret;
> }
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260821195259.2688377-1-jremus@linux.ibm.com?part=12
next prev parent reply other threads:[~2026-08-21 20:18 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 19:52 [RFC PATCH v2 00/24] unwind_user: Implement .eh_frame handling Jens Remus
2026-08-21 19:52 ` [RFC PATCH v2 01/24] unwind_user: Add generic and arch-specific headers to MAINTAINERS Jens Remus
2026-08-21 19:52 ` [RFC PATCH v2 02/24] unwind_user: Stop when reaching an outermost frame Jens Remus
2026-08-21 20:00 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 03/24] unwind_user: Enable archs that pass RA in a register Jens Remus
2026-08-21 20:02 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 04/24] unwind_user: Flexible FP/RA recovery rules Jens Remus
2026-08-21 20:03 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 05/24] unwind_user: Flexible CFA " Jens Remus
2026-08-21 20:03 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 06/24] unwind_user: Enable archs that define CFA = SP_callsite + offset Jens Remus
2026-08-21 20:03 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 07/24] unwind_user/eh_frame: Add support for reading .eh_frame_hdr section Jens Remus
2026-08-21 20:06 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 08/24] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree Jens Remus
2026-08-21 20:13 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 09/24] unwind_user/eh_frame: Add support for reading .eh_frame section Jens Remus
2026-08-21 20:16 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 10/24] unwind_user/eh_frame: Detect .eh_frame_hdr sections in executables Jens Remus
2026-08-21 20:10 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 11/24] unwind_user/eh_frame: Wire up unwind_user to eh_frame Jens Remus
2026-08-21 20:07 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 12/24] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption Jens Remus
2026-08-21 20:18 ` sashiko-bot [this message]
2026-08-21 19:52 ` [RFC PATCH v2 13/24] unwind_user/eh_frame: Show file name in debug output Jens Remus
2026-08-21 20:06 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 14/24] unwind_user/eh_frame: Add .eh_frame[_hdr] validation option Jens Remus
2026-08-21 20:10 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 15/24] unwind_user/eh_frame: Duplicate registered .eh_frame[_hdr] section data on clone/fork Jens Remus
2026-08-21 20:09 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 16/24] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size Jens Remus
2026-08-21 20:03 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 17/24] unwind_user/eh_frame: Add support for DWARF expressions Jens Remus
2026-08-21 20:18 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 18/24] x86/uaccess: Add unsafe_copy_from_user() implementation Jens Remus
2026-08-21 20:11 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 19/24] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86 Jens Remus
2026-08-21 20:16 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 20/24] unwind_user/eh_frame/x86: Handle PLT expressions Jens Remus
2026-08-21 20:17 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 21/24] unwind_user/eh_frame/x86: Handle DRAP expressions Jens Remus
2026-08-21 20:15 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 22/24] s390/ptrace: Provide frame_pointer() Jens Remus
2026-08-21 20:07 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 23/24] unwind_user/eh_frame/s390: Enable eh_frame unwinding on s390 Jens Remus
2026-08-21 20:15 ` sashiko-bot
2026-08-21 19:52 ` [RFC PATCH v2 24/24] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections Jens Remus
2026-08-21 20:22 ` sashiko-bot
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=20260821201820.81B8D1F000E9@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox