Re: [RFC PATCH v1 17/25] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size
From: sashiko-bot@kernel.org
Date: 2026-08-18 15:04:48
Also in:
linux-s390
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] An integer overflow when evaluating `cur + expr_len` bypasses bounds checks, allowing an attacker to move the instruction pointer backward and trap the kernel in an infinite loop. - [High] The CFI interpreter loop does not impose a maximum execution limit, allowing an attacker to stall the CPU by providing a maliciously crafted, highly padded sequence of CFI instructions. --
--- Patch [17]: [RFC PATCH v1 17/25] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size ---commit e1c2b0ab16134f39bfe2a1cb074739516466f777 Author: Jens Remus [off-list ref] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size This commit updates the unwind mechanism to safely ignore the DW_CFA_GNU_args_size DWARF instruction. This instruction is used by GCC to track exception handling stack sizes, but is not needed for kernel stack tracing.
quoted hunk ↗ jump to hunk
diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index ac288cec8021f..64176242b7d8f 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c
[ ... ]
quoted hunk ↗ jump to hunk
@@ -1012,6 +1012,17 @@ static __always_inline int __do_cfi_insn(struct eh_frame_section *sec, break; } + case DW_CFA_GNU_args_size: { + unsigned long args_size; + + ret = read_uleb128(&cur, end, &args_size); + if (ret) + return ret; + + /* Ignore DW_CFA_GNU_args_size */ + break; + } + case DW_CFA_remember_state: if (ctx->stack_depth >= EH_FRAME_MAX_STATE_STACK) return -EINVAL;
[Severity: High]
This is a pre-existing issue, but does this code allow an integer overflow
when evaluating cur + expr_len?
kernel/unwind/eh_frame.c:__do_cfi_insn() {
...
case DW_CFA_val_expression: {
unsigned long reg, expr_len;
ret = read_uleb128(&cur, end, ®);
if (ret)
return ret;
ret = read_uleb128(&cur, end, &expr_len);
if (ret)
return ret;
if (cur + expr_len > end)
return -EINVAL;
...
}
If a maliciously crafted .eh_frame section provides an extremely large
expr_len value, cur + expr_len can wrap around to a value less than end.
This bypasses the bounds check, and when the instruction pointer cur is
updated via cur += expr_len, it moves backwards.
Since the unwinder operates on user-supplied call frame information, can
this trap the kernel in an uninterruptible infinite loop and cause a local
denial of service?
[Severity: High]
This is a pre-existing issue, but is it possible for this loop to run without
an execution limit?
kernel/unwind/eh_frame.c:__do_cfi_program() {
...
cur = fde->cfi_insn_start;
while (cur < fde->cfi_insn_end && ip <= target_ip) {
ret = __do_cfi_insn(sec, fde, &cur, fde->cfi_insn_end, &ip, target_ip, ctx);
if (ret)
return ret;
}
...
}
If a local attacker maps a maximally sized frame description entry filled
with DW_CFA_nop instructions, the kernel will sequentially process billions
of instructions without yielding or aborting.
Since this can run in non-preemptible or non-maskable interrupt contexts
during stack unwinding, can this stall the processor and trigger a
watchdog panic?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260818144954.2320378-1-jremus@linux.ibm.com?part=17