Re: [RFC PATCH v1 16/25] unwind_user/eh_frame: Add linear .eh_frame search fallback
From: Jens Remus <hidden>
Date: 2026-08-21 19:41:42
Also in:
linux-s390, sashiko-reviews
On 8/18/2026 5:06 PM, sashiko-bot@kernel.org wrote:
This commit adds a linear search fallback for .eh_frame sections when the .eh_frame_hdr lacks a binary search table. It also introduces validation logic for the referenced .eh_frame section, guarded by a new config option EH_FRAME_LINEAR_SEARCH.
quoted
diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
quoted
@@ -590,6 +589,82 @@ static __always_inline int __find_fde(struct eh_frame_section *sec, return -EFAULT; } +#ifdef CONFIG_EH_FRAME_LINEAR_SEARCH + +static __always_inline int __find_fde_lsearch(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + unsigned long start = sec->eh_frame_start; + unsigned long vma_end = sec->eh_frame_vma_end; + unsigned long cur; + int ret; + + /* Linear search through .eh_frame */ + cur = start; + while (cur >= start && cur < vma_end) {[Severity: High] Since the section header only provides the start address, this loop iterates all the way to vma_end. As noted in the commit message, many binaries lack a zero terminator. If an unresolved IP is scanned, will this read past the actual section boundary into padding or other sections, return -EINVAL on garbage data, and subsequently cause the caller to permanently remove the section?
True. I mentioned this in the patch description and notes that linear .eh_frame search should better not be used. I will drop this patch, as the issue is now documented with RFC v1.
quoted
+#else /* !CONFIG_EH_FRAME_LINEAR_SEARCH */ + +static __always_inline int __find_fde_lsearch(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + return 0; +}[Severity: Critical] Does returning 0 here falsely indicate success when linear search is disabled?
My bad! Got this wrong during rebase when splitting out linear search into this separate patch. Would need to return -ENOENT instead if this should ever get picked up again.
If a binary lacks a search table, __find_fde() will call this stub.
Returning 0 causes the caller, eh_frame_find(), to proceed with an
uninitialized fde stack variable:
kernel/unwind/eh_frame.c:eh_frame_find() {
struct eh_frame_fde fde;
...
ret = __find_fde(sec, ip, &fde);
if (!ret)
ret = __find_frame_row(sec, &fde, ip, frame);
...
}
Could this lead to corrupted stack traces or arbitrary memory reads by
consuming the uninitialized fde context? Should this return -ENOENT
instead?True. See above.
quoted
+static int eh_frame_validate_section(struct eh_frame_section *sec) +{ + int ret; + + /* + * Validate .eh_frame_hdr binary search table + * (incl. all referenced FDE and CIE in .eh_frame). + */ + ret = eh_frame_validate_eh_frame_hdr(sec); + if (ret) + return ret; + + /* + * Validate .eh_frame CIE and FDE. Skip if linear search + * is disabled, as many .eh_frame sections lack a zero + * terminator and the section end if unknown. + */ + if (IS_ENABLED(CONFIG_EH_FRAME_LINEAR_SEARCH)) { + ret = eh_frame_validate_eh_frame(sec); + if (ret) + return ret; + }[Severity: High] Does this unconditionally apply linear validation to all binaries when CONFIG_EH_FRAME_LINEAR_SEARCH is enabled, even if they already have a valid binary search table?
Yes, that was on purpose, as it would validate both .eh_frame_hdr and .eh_frame sections.
If the binary lacks a zero terminator, eh_frame_validate_eh_frame() will read out of bounds up to vma_end, fail with -EINVAL, and reject the entire section. Will this permanently break unwinding for valid binaries that were previously working fine via the binary search table?quoted
+ + return 0; +}
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/