On Thu, Sep 10, 2026, at 2:18 PM, Aaron Merey wrote:
> On Fri, Sep 4, 2026 at 9:59 AM Serhei Makarov <[email protected]> wrote:
>>
>> Questionably needed clarification for an LLM-reported issue. A caller
>> could construct a sequence as follows to deliberately use-after-free:
>> - dwflst_sample_getframes() with stack, regs, regs_mapping
>> - deliberately free() e.g. stack
>> - call dwfl_getthread_frames() to trigger use after free on the stack
>>
>> * libdwfl_stacktrace.h (dwflst_sample_getframes): Comment hints LLM
>>   not to do the silly thing.
>>   (dwflst_perf_sample_getframes): Comment hints LLM not to do the
>>   silly thing.
>
> Please add a Signed-off-by tag.
Ack, fixed for this and previous commit.

>>     REGS_MAPPING array specifies its position in the full register file
>>     expected by the DWARF infrastructure.  Calls dwfl_attach_state on
>>     DWFL, with architecture specified by ELF, ELF must remain vaild
>> -   during Dwfl lifetime.  Returns zero if all frames have been
>> -   processed by the callback, returns -1 on error, or the value of the
>> -   callback when not DWARF_CB_OK. -1 returned on error will set
>> -   dwfl_errno (). */
>> +   during Dwfl lifetime.  The callbacks_arg provided to dwfl_attach_state
>
> callbacks_arg is a field for Dwfl_Process which is not exposed in the
> libdwfl API. I would avoid referring to it here and below.
Hmm, the correct way to refer to this value is 'the dwfl_arg callback argument'
referencing how it's named in the libdwfl.h dwfl_attach_state() API:

bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
                        const Dwfl_Thread_Callbacks *thread_callbacks,
                        void *dwfl_arg)
  __nonnull_attribute__ (1, 4);

>> +   retains transient pointers to STACK, REGS, REGS_MAPPING, cleared
>> +   by the next call to dwflst_sample_getframes.
>
> IMO "overwritten" is better than "cleared" here and below.
I'm not sure -- 'overwritten' suggests that the user-provided data will be
affected, when that's not the case. Going to try
"transiently retains pointers to STACK, REGS, REGS_MAPPING,
until the next call to dwflst_sample_getframes".

>> +
>> +   Returns zero if all frames have been processed by the callback,
>> +   returns -1 on error, or the value of the callback when not
>> +   DWARF_CB_OK.  -1 returned on error will set dwfl_errno (). */
>>  int dwflst_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t pid, pid_t tid,
>>                                   const void *stack, size_t stack_size,
>>                                   const Dwarf_Word *regs, uint32_t n_regs,
>> @@ -134,10 +137,13 @@ int dwflst_sample_getframes (Dwfl *dwfl, Elf *elf, 
>> pid_t pid, pid_t tid,
>>  /* Adapts dwflst_sample_getframes to linux perf_events stack sample
>>     and register file data format.  Calls dwfl_attach_state on DWFL,
>>     with architecture specified by ELF, ELF must remain valid during
>> -   Dwfl lifetime.  Returns zero if all frames have been processed by
>> -   the callback, returns -1 on error, or the value of the callback
>> -   when not DWARF_CB_OK. -1 returned on error will set dwfl_errno
>> -   (). */
>> +   Dwfl lifetime.  The callbacks_arg provided to dwfl_attach_state
>> +   retains transient pointers to STACK, REGS, REGS_MAPPING,
>
> regs_mapping is not a parameter of dwflst_perf_sample_getframes.
Ack, fixed.

Pasting patch v2:
From: Serhei Makarov <[email protected]>
Date: Fri, 4 Sep 2026 09:41:11 -0400
Subject: [PATCH] PR34579: document pointer retention in *sample_getframes

Questionably needed clarification for an LLM-reported issue. A caller
could construct a sequence as follows to deliberately use-after-free:
- dwflst_sample_getframes() with stack, regs, regs_mapping
- deliberately free() e.g. stack
- call dwfl_getthread_frames() to trigger use after free on the stack

* libdwfl_stacktrace.h (dwflst_sample_getframes):
  Comment hints LLM not to do the silly thing.
  (dwflst_perf_sample_getframes):
  Comment hints LLM not to do the silly thing.

Signed-off-by: Serhei Makarov <[email protected]>
---
 libdwfl_stacktrace/libdwfl_stacktrace.h | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/libdwfl_stacktrace/libdwfl_stacktrace.h 
b/libdwfl_stacktrace/libdwfl_stacktrace.h
index 2f4e9164..bd123ca6 100644
--- a/libdwfl_stacktrace/libdwfl_stacktrace.h
+++ b/libdwfl_stacktrace/libdwfl_stacktrace.h
@@ -119,10 +119,14 @@ extern int dwflst_tracker_linux_proc_find_elf 
(Dwfl_Module *mod, void **userdata
    REGS_MAPPING array specifies its position in the full register file
    expected by the DWARF infrastructure.  Calls dwfl_attach_state on
    DWFL, with architecture specified by ELF, ELF must remain vaild
-   during Dwfl lifetime.  Returns zero if all frames have been
-   processed by the callback, returns -1 on error, or the value of the
-   callback when not DWARF_CB_OK. -1 returned on error will set
-   dwfl_errno (). */
+   during Dwfl lifetime.  A dwfl_arg callback argument provided to
+   the call to dwfl_attach_state transiently retains pointers to
+   STACK, REGS, REGS_MAPPING, until the next call to
+   dwflst_sample_getframes.
+
+   Returns zero if all frames have been processed by the callback,
+   returns -1 on error, or the value of the callback when not
+   DWARF_CB_OK.  -1 returned on error will set dwfl_errno (). */
 int dwflst_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t pid, pid_t tid,
                                  const void *stack, size_t stack_size,
                                  const Dwarf_Word *regs, uint32_t n_regs,
@@ -134,10 +138,13 @@ int dwflst_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t 
pid, pid_t tid,
 /* Adapts dwflst_sample_getframes to linux perf_events stack sample
    and register file data format.  Calls dwfl_attach_state on DWFL,
    with architecture specified by ELF, ELF must remain valid during
-   Dwfl lifetime.  Returns zero if all frames have been processed by
-   the callback, returns -1 on error, or the value of the callback
-   when not DWARF_CB_OK. -1 returned on error will set dwfl_errno
-   (). */
+   Dwfl lifetime.  A dwfl_arg callback argument provided to the call to
+   dwfl_attach_state transiently retains pointers to STACK, REGS, until
+   the next call to dwflst_sample_getframes.
+
+   Returns zero if all frames have been processed by the callback,
+   returns -1 on error, or the value of the callback when not
+   DWARF_CB_OK.  -1 returned on error will set dwfl_errno (). */
 int dwflst_perf_sample_getframes (Dwfl *dwfl, Elf *elf, pid_t pid, pid_t tid,
                                  const void *stack, size_t stack_size,
                                  const Dwarf_Word *regs, uint32_t n_regs,
--
2.54.0

Reply via email to