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 <[email protected]> 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. > 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 [ ... ] > @@ -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/[email protected]?part=17
