On 8/18/2026 5:06 PM, [email protected] 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.
>> diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
>> @@ -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.
>> +#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.
>> +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?
>
>> +
>> + return 0;
>> +}
>
Regards,
Jens
--
Jens Remus
Linux on Z Development (D3303)
[email protected] / [email protected]
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/