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

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] Using `unsafe_copy_from_user` inside a `scoped_user_read_access_size` block prematurely clears the AC flag on x86, causing subsequent user memory accesses to trigger a fatal Page Fault (kernel panic).
- [High] Integer overflow in the DWARF expression bounds check allows an infinite parsing loop in kernel space.
- [High] The `cfa_offset` field of the CFI context state is passed to the unwinder uninitialized if a malformed CFI program starts with a `DW_CFA_def_cfa_register` instruction.
- [Medium] Calling an out-of-line function within a UACCESS region violates objtool's safe execution rules.
--

--- Patch [18]: [RFC PATCH v1 18/25] unwind_user/eh_frame: Add support for DWARF expressions ---
commit 8c411d17e9c2d4af2ed33eb236e117fc360ae4f2
Author: Jens Remus <jremus@linux.ibm.com>
Subject: unwind_user/eh_frame: Add support for DWARF expressions

This commit enables architectures to handle DWARF expressions in DWARF CFI
instructions. It limits the maximum expression length to a reasonable size
and provides inline stubs for architectures to override.

> diff --git a/include/linux/unwind_user_eh_frame_types.h b/include/linux/unwind_user_eh_frame_types.h
> new file mode 100644
> --- /dev/null
> +++ b/include/linux/unwind_user_eh_frame_types.h
> @@ -0,0 +1,37 @@
[ ... ]
> +struct eh_frame_reg_state {
> +	/* CFA recovery rule */
> +	enum eh_frame_cfa_rule cfa_rule;
> +	unsigned long cfa_regnum;
> +	long cfa_offset;

[Severity: High]
What ensures cfa_offset is initialized when processing CFI programs?

When struct eh_frame_cfi_context ctx is allocated on the kernel stack in
__do_cfi_program(), its state.cfa_rule is initialized, but state.cfa_offset
is not.

If a user-supplied .eh_frame begins with DW_CFA_def_cfa_register, it sets
ctx.state.cfa_rule = CFA_REG_OFFSET but leaves cfa_offset untouched.

When __find_frame_row() executes, it verifies cfa_rule == CFA_REG_OFFSET
and unconditionally reads the uninitialized kernel stack memory. Could this
cause the unwinder to use unpredictable values for the CFA offset?

> +
> +	/* FP and RA recovery rules (SP uses implicit recovery) */
> +	enum eh_frame_reg_rule reg_rule[NR_REGS];
> +	unsigned long reg_regnum[NR_REGS];
> +	long reg_offset[NR_REGS];
> +};

[ ... ]

> 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
[ ... ]
> @@ -839,6 +808,27 @@ static __always_inline int __do_cfi_insn(struct eh_frame_section *sec,
>  			break;
>  		}
>  
> +		case DW_CFA_def_cfa_expression: {
> +			unsigned long expr_len;
> +			char expr[EH_FRAME_MAX_EXPRESSION_LENGTH];
> +
> +			ret = read_uleb128(&cur, end, &expr_len);
> +			if (ret)
> +				return ret;
> +
> +			if (cur + expr_len > end)

[Severity: High]
Can the pointer arithmetic wrap around if expr_len is maliciously large?

Since expr_len is parsed from untrusted user input as an unsigned long, a
large value could overflow cur + expr_len and wrap to a small value,
bypassing this check against end.

If this occurs, the parsing loop would advance cur by the overflowed
expr_len, moving cur backwards. Would this lead to an infinite parsing loop
and a hard lockup?

> +				return -EINVAL;
> +
> +			if (expr_len > sizeof(expr))
> +				return -EOPNOTSUPP;
> +			unsafe_copy_from_user(&expr, (void __user *)cur, expr_len, Efault);

[Severity: Critical]
Might unsafe_copy_from_user() improperly toggle SMAP during expression
parsing?

Because this parsing runs inside a scoped_user_read_access_size block,
calling unsafe_copy_from_user() on x86 defaults to __copy_from_user(),
which executes its own stac() and clac() instructions.

The inner clac() instruction clears the AC flag prematurely, ending the
UACCESS region while the outer block assumes it is still open.

When the loop continues to parse the next instruction using
UNSAFE_GET_USER_INC, it will attempt a direct user memory read with the AC
flag cleared. Will this result in a fatal page fault?

> +			ret = eh_frame_do_def_cfa_expression(expr, expr_len, target_ip, &ctx->state);

[Severity: Medium]
Is it safe to call an architecture hook inside a UACCESS region?

If an architecture overrides eh_frame_do_def_cfa_expression() with an
out-of-line external function, it will trigger objtool's 'call to XXX()
with UACCESS enabled' warning.

Executing arbitrary functions with the AC flag set is strictly forbidden
on x86 to prevent SMAP bypasses.

> +			if (ret)
> +				return ret;
> +			cur += expr_len;
> +			break;
> +		}

[ ... ]

> @@ -1005,9 +995,19 @@ static __always_inline int __do_cfi_insn(struct eh_frame_section *sec,
>  			if (cur + expr_len > end)
>  				return -EINVAL;
>  
> -			if (reg == EH_FRAME_REG_SP || reg == EH_FRAME_REG_FP || reg == EH_FRAME_REG_RA)
> -				return -EOPNOTSUPP;
> +			if (reg == EH_FRAME_REG_SP || reg == EH_FRAME_REG_FP || reg == EH_FRAME_REG_RA) {
> +				char expr[EH_FRAME_MAX_EXPRESSION_LENGTH];
>  
> +				if (expr_len > sizeof(expr))
> +					return -EOPNOTSUPP;
> +				unsafe_copy_from_user(&expr, (void __user *)cur, expr_len, Efault);

[Severity: Critical]
Does this copy run into the same SMAP clearing issue as mentioned above?

Calling unsafe_copy_from_user() here will also execute a clac() instruction
and clear the AC flag, causing subsequent user memory accesses to trigger a
fatal page fault.

> +				if (opcode == DW_CFA_expression)
> +					ret = eh_frame_do_expression(reg, expr, expr_len, target_ip, &ctx->state);
> +				else
> +					ret = eh_frame_do_val_expression(reg, expr, expr_len, target_ip, &ctx->state);

[Severity: Medium]
Could these hooks also cause objtool UACCESS warnings?

Similar to eh_frame_do_def_cfa_expression(), overriding these with external
functions could lead to executing arbitrary code with the AC flag set.

> +				if (ret)
> +					return ret;
> +			}
>  			cur += expr_len;
>  			break;
>  		}

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

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