From: Jens Remus <jremus@linux.ibm.com>
To: Steven Rostedt <rostedt@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>,
Indu Bhagat <ibhagatgnu@gmail.com>,
bpf@vger.kernel.org, sashiko@lists.linux.dev
Subject: Re: [PATCH v14 05/19] unwind_user/sframe: Add support for reading .sframe contents
Date: Wed, 6 May 2026 17:29:57 +0200 [thread overview]
Message-ID: <82fca24b-d166-4e87-abc9-07cfc9cb8160@linux.ibm.com> (raw)
In-Reply-To: <20260506110142.7b2943d7@fedora>
On 5/6/2026 5:01 PM, Steven Rostedt wrote:
> On Wed, 6 May 2026 16:34:34 +0200
> Jens Remus <jremus@linux.ibm.com> wrote:
>
>>>> +static __always_inline int __read_fre(struct sframe_section *sec,
>>>> + struct sframe_fde_internal *fde,
>>>> + unsigned long fre_addr,
>>>> + struct sframe_fre_internal *fre)
>>>> +{
>>> [ ... ]
>>>> + if (fre_addr + addr_size + 1 > sec->fres_end)
>>>> + return -EFAULT;
>>>> +
>>>> + UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault);
>>>
>>> Will this cause alignment faults on architectures with strict alignment
>>> requirements?
>>>
>>> The .sframe format uses packed structures and variable-length datawords. The
>>> cur pointer might be unaligned here, and UNSAFE_GET_USER_INC() performs
>>> 16-bit or 32-bit reads via unsafe_get_user().
>>
>> IIUC this should not be an issue for x86-64, s390, and arm64.
>
> Do we have a way to make sure that sframe support will always be for
> architectures that can handle alignment issues like this? There should
> be something to force this via configs or something that will trigger a
> warning or bug if this is built for architectures that can't handle
> this alignment.
Any suggestions are very welcome.
>>>> +
>>>> + fre_addr = sec->fres_start + fde->fres_off;
>>>> +
>>>> + for (i = 0; i < fde->fres_num; i++) {
>>>
>>> Can this loop cause a hard lockup in atomic context?
>>>
>>> fde->fres_num is a 32-bit value copied from user space without validation.
>>> Since sframe_find() is designed to be called by unwinders in NMI context, an
>
> What? No. This looks to be a hallucination. sframe_find() will never be
> called in NMI context. In fact, it can only be called in task context.
>
>>> attacker could provide a very large number of valid entries. Executing
>>> billions of iterations and unsafe_get_user() calls could stall the CPU
>>> and trigger the hard lockup detector.
>>
>> Please advise.
>
> That said, we should verify that fde->fres_num is at least always
> smaller than the size of the table.
If we carry the .sframe header sfh->num_fres over to a new sec->num_fres
then __read_fde() could check:
if (_fda.fres_num > sec->num_fres)
return -EINVAL;
But I am not sure if that check provides much benefit, as fde->fres_num
is relative to fde->fres_off, which points into the
[sec->fres_start, sec->fres_end[ part of the .sframe section.
So even a small fde->fres_num might be out of range. Given the FRE are
variable size, it is not easily possible to check upfront in
__read_fde() whether the fde->fres_num is valid.
The validity is checked later in __read_fre() before any fields are read
from the FRE, with fre_addr = sec->fres_start + fde->fres_off being
passed as argument:
if (fre_addr + addr_size + 1 > sec->fres_end)
return -EFAULT;
[...]
if (cur + (dataword_count * dataword_size) > sec->fres_end)
return -EFAULT;
>
>>
>>>
>>>> + int ret;
>>>> +
>>>
>>> [ ... ]
>>>
>>>> @@ -120,8 +449,10 @@ int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
>>>> sec->text_end = text_end;
>>>>
>>>> ret = sframe_read_header(sec);
>>>> - if (ret)
>>>> + if (ret) {
>>>> + dbg_print_header(sec);
>>>> goto err_free;
>>>> + }
>>>
>>> Can shdr.fre_len cause an integer overflow on 32-bit architectures during
>>> header parsing?
>>>
>>> If a malicious user provides a large fre_len in the header, fres_end
>>> (calculated as fres_start + shdr.fre_len) could wrap around the 32-bit
>>> address space. This would bypass the bounds check in sframe_read_header(),
>>> allowing fres_start and fdes_start to point into kernel memory. Later, when
>>> __read_fde() and __find_fre() use unsafe_get_user(), this could lead to
>>> arbitrary kernel memory disclosure.
>>
>> SFrame is currently only supported on 64-bit architectures (i.e. x86-64,
>> arm64, s390 64-bit). So unsigned long fres_end should always be 64-bit.
>> Do we need to add the following to the header parsing?
>>
>> if (fdes_start >= fdes_end || fres_start >= fres_end) {
>> dbg_sec("inconsistent FDE/FRE start/end address\n");
>> return -EINVAL;
>> }
>
> I guess this wouldn't hurt.
Ok.
>>>>
>>>> ret = mtree_insert_range(sframe_mt, sec->text_start, sec->text_end, sec, GFP_KERNEL);
>>>
>>> Does passing sec->text_end directly as the last parameter to
>>> mtree_insert_range() break contiguous mappings?
>>>
>>> mtree_insert_range() expects the last boundary to be inclusive, but
>>> sec->text_end represents the exclusive end address of the executable segment.
>>> If user space maps seamlessly contiguous text segments, the insertion for the
>>> second segment might overlap with the claimed end of the first, causing it to
>>> fail with -EEXIST.
>>
>> Addressed in previous patch.
>
> And I just sent a patch to fix the documentation of
> mtree_insert_range() to update the kerneldoc to explicitly state it is
> inclusive :-p
Thanks!
>>
>>>
>>>> if (ret) {
>>>> dbg("mtree_insert_range failed: text=%lx-%lx\n",
>>>
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/
next prev parent reply other threads:[~2026-05-06 15:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260505121718.3572346-6-jremus@linux.ibm.com>
[not found] ` <20260505185932.C708CC2BCB4@smtp.kernel.org>
2026-05-06 14:34 ` [PATCH v14 05/19] unwind_user/sframe: Add support for reading .sframe contents Jens Remus
2026-05-06 15:01 ` Steven Rostedt
2026-05-06 15:29 ` Jens Remus [this message]
2026-05-08 9:49 ` Jens Remus
2026-05-08 23:04 ` Indu Bhagat
2026-05-12 13:35 ` Jens Remus
2026-05-13 12:22 ` Steven Rostedt
2026-05-08 23:03 ` Indu Bhagat
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=82fca24b-d166-4e87-abc9-07cfc9cb8160@linux.ibm.com \
--to=jremus@linux.ibm.com \
--cc=bpf@vger.kernel.org \
--cc=ibhagatgnu@gmail.com \
--cc=jpoimboe@kernel.org \
--cc=rostedt@kernel.org \
--cc=sashiko@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox