All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jens Remus" <jremus@linux.ibm.com>
Cc: "Christian Borntraeger" <borntraeger@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	linux-s390@vger.kernel.org, "Vasily Gorbik" <gor@linux.ibm.com>,
	linux-trace-kernel@vger.kernel.org,
	"Alexander Gordeev" <agordeev@linux.ibm.com>
Subject: Re: [RFC PATCH v1 09/25] unwind_user/eh_frame: Add support for reading .eh_frame section
Date: Tue, 18 Aug 2026 15:05:48 +0000	[thread overview]
Message-ID: <20260818150549.2009E1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260818144954.2320378-10-jremus@linux.ibm.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] `DW_CFA_restore` incorrectly clears register rules instead of restoring the CIE's initial rule.
- [High] Uninitialized usage of `fde->func_addr` when decoding an FDE's start address via `DW_EH_PE_funcrel`.
- [High] The `eh_frame_cfi_context` struct is partially initialized, exposing uninitialized stack memory via `cfa_offset`.
- [Low] Incompatible pointer type passed to `read_uleb128()` in `DW_CFA_offset` instruction parsing.
--

--- Patch [9]: [RFC PATCH v1 09/25] unwind_user/eh_frame: Add support for reading .eh_frame section ---
commit 7603506904ca3b69840f3790ec49f48b9d3d54fb
Author: Jens Remus <jremus@linux.ibm.com>

unwind_user/eh_frame: Add support for reading .eh_frame section

This patch adds an eh_frame_find interface to parse DWARF Call Frame
Information from the .eh_frame section for unwinding user space stacks. It
reads Common Information Entries, Frame Description Entries, and evaluates
DWARF CFI instructions to restore registers.

> 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 __always_inline int read_encoded_pointer(struct eh_frame_section *sec,
> +                                               struct eh_frame_fde *fde,
>                                                 unsigned long *addr,
>                                                 unsigned long end,
>                                                 u8 encoding,
>                                                 unsigned long *value)
>  {
[ ... ]
> +	case DW_EH_PE_funcrel:
> +		if (!fde)
> +			return -EINVAL;
> +		result = fde->func_addr;
> +		break;
[ ... ]
> +static __always_inline int __read_fde(struct eh_frame_section *sec,
> +				      unsigned long fde_addr,
> +				      struct eh_frame_fde *fde)
> +{
[ ... ]
> +	scoped_user_read_access_size(fde_ptr, 4 + length, Efault) {
> +		/* Read PC begin (function start address) */
> +		ret = read_encoded_pointer(sec, fde, &cur, end, fde->cie.fde_addr_enc, &func_addr);

[Severity: High]
Does this code use an uninitialized value for the function address?

If the user-space eh_frame section specifies the DW_EH_PE_funcrel
encoding for fde_addr_enc, read_encoded_pointer() will attempt to evaluate
fde->func_addr.

However, fde->func_addr is not populated until the end of __read_fde(),
after the function address has already been parsed. Could this allow a
crafted eh_frame to use uninitialized kernel stack memory in its
address calculation?

> +		if (ret)
> +			return ret;
> +		if (func_addr < sec->text_start || func_addr >= sec->text_end)
> +			return -EINVAL;
[ ... ]
> +	fde->func_addr		= func_addr;
[ ... ]
> +static __always_inline int __do_cfi_insn(struct eh_frame_section *sec,
> +					 struct eh_frame_fde *fde,
> +					 unsigned long *cur_ptr,
> +					 unsigned long end,
> +					 unsigned long *ip_ptr,
> +					 unsigned long target_ip,
> +					 struct eh_frame_cfi_context *ctx)
> +{
[ ... ]
> +	case DW_CFA_offset: {
> +		u8 reg = DW_CFA_operand(opcode);
> +		long offset;
> +		int idx;
> +
> +		ret = read_uleb128(&cur, end, &offset);

[Severity: Low]
Is the offset variable the correct type here?

The read_uleb128() function expects a pointer to an unsigned long, but
offset is defined as a signed long. This creates an incompatible pointer
type warning during the build.

> +		if (ret)
> +			return ret;
> +		offset *= fde->cie.data_align;
[ ... ]
> +	case DW_CFA_restore: {
> +		u8 reg = DW_CFA_operand(opcode);
> +		int idx;
> +
> +		idx = reg_to_index(reg);
> +		if (idx >= 0)
> +			ctx->state.reg_rule[idx] = REG_UNDEFINED_IMPLICIT;
> +		break;
> +	}

[Severity: High]
Does this instruction handler violate the DWARF specification?

The DWARF standard requires DW_CFA_restore to change the rule for the
indicated register back to the rule assigned by the initial instructions in
the CIE. By unconditionally setting it to REG_UNDEFINED_IMPLICIT instead
of restoring the CIE initial rule, this could corrupt the register recovery
state and cause unwinding to fail.

[ ... ]
> +		case DW_CFA_def_cfa_register: {
> +			unsigned long reg;
> +
> +			ret = read_uleb128(&cur, end, &reg);
> +			if (ret)
> +				return ret;
> +
> +			ctx->state.cfa_rule = CFA_REG_OFFSET;
> +			ctx->state.cfa_regnum = reg;
> +			break;
> +		}
[ ... ]
> +static __always_inline int __find_frame_row(struct eh_frame_section *sec,
> +					    struct eh_frame_fde *fde,
> +					    unsigned long ip,
> +					    struct unwind_user_frame *frame)
> +{
> +	struct eh_frame_cfi_context ctx;
> +	int ret;
> +
> +	/* TODO: Signal frame - not supported yet */
> +	if (fde->cie.signal_frame)
> +		return -EOPNOTSUPP;
> +
> +	ret = __do_cfi_program(sec, fde, ip, &ctx);

[Severity: High]
Can this leak kernel stack memory?

The eh_frame_cfi_context ctx structure is allocated on the stack without
being zero-initialized. In __do_cfi_program(), some fields are manually
initialized, but cfa_offset is omitted.

If an attacker provides a crafted eh_frame using DW_CFA_def_cfa_register
as the first state-modifying instruction, it changes cfa_rule to
CFA_REG_OFFSET without setting cfa_offset. The uninitialized kernel stack
garbage in ctx.state.cfa_offset is then subsequently copied into
frame->cfa.offset, allowing it to be used as an offset to read memory.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260818144954.2320378-1-jremus@linux.ibm.com?part=9

  reply	other threads:[~2026-08-18 15:05 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
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 [this message]
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=20260818150549.2009E1F000E9@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.