Thread (67 messages) 67 messages, 3 authors, 2026-08-21

Re: [RFC PATCH v1 18/25] unwind_user/eh_frame: Add support for DWARF expressions

From: Jens Remus <hidden>
Date: 2026-08-21 19:41:55
Also in: linux-s390, sashiko-reviews

On 8/18/2026 5:13 PM, sashiko-bot@kernel.org wrote:
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.
quoted
diff --git a/include/linux/unwind_user_eh_frame_types.h b/include/linux/unwind_user_eh_frame_types.h
quoted
+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.
Fixed in "unwind_user/eh_frame: Add support for reading .eh_frame
section".
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?
quoted
diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
quoted
+		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)
			if (cur + expr_len < cur || 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?
Valid.  Improved overflow check.
quoted
+				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?
False.  IIUC config option HAVE_UNWIND_USER_EH_FRAME cannot be manually
enabled.  Therefore this code cannot be enabled on any architecture,
including x86.

unsafe_copy_from_user() is added for x86 by subsequent patch
"[RFC PATCH v1 19/25] x86/uaccess: Add unsafe_copy_from_user()
implementation".
quoted
+			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.
Steven, Josh, what are your thoughts?
quoted
+			if (ret)
+				return ret;
+			cur += expr_len;
+			break;
+		}
Thanks and regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help