Linux Trace Kernel
 help / color / mirror / Atom feed
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

  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