bosswnx commented on issue #67428:
URL: https://github.com/apache/doris/issues/67428#issuecomment-5506340466

   Thanks for the thorough triage — the ownership analysis matches ours, and 
the **attribution boundary correction is accepted**: I verified that neither 
#66191 nor #66899 touches the flush-task lifetime code (`delta_writer` / 
`memtable_writer` / `memtable_flush_executor` / the `rowset_builder` ownership 
paths — #66191 only adds tablet-state checks and a migration lock in 
`GroupRowsetBuilder::init`; #66899 only adds tests and a segment-flusher format 
change). The UAF is timing-sensitive and probabilistic; the new suites merely 
widen the exposure.
   
   Per the "Missing evidence" request, the complete three ASAN stacks from 
build 1036154 (PR #67402, base `952bfcbb40fa`) are attached below — full 
frames, not selected ones.
   
   **READ of size 8 (thread T1919, mf_normal):**
   
   ```
   ==48480==ERROR: AddressSanitizer: heap-use-after-free on address 
0x7d3e73b61f30
   READ of size 8 at 0x7d3e73b61f30 thread T1919 (mf_normal [work)
       #0 
std::__shared_ptr<doris::segment_v2::SegmentAllocatedLsnMap>::operator bool() 
const shared_ptr_base.h:1677:16
       #2 doris::RowsetWriterContext::remove_segment_allocated_lsns(long) 
be/src/storage/rowset/rowset_writer_context.h:202:9
       #3 doris::SharedMemtable::~SharedMemtable() 
be/src/load/memtable/memtable_flush_executor.cpp:124:21
       #7 doris::PartOfGroupMemtableFlushTask::~PartOfGroupMemtableFlushTask() 
be/src/load/memtable/memtable_flush_executor.cpp:82:7
      #13 doris::ThreadPool::dispatch_thread() be/src/util/threadpool.cpp:628:23
   ```
   
   **Freed by thread T1919 (end of run()):**
   
   ```
       #4 doris::FlushToken::~FlushToken() 
be/src/load/memtable/memtable_flush_executor.h:92:7
       #8 doris::PartOfGroupMemtableFlushTask::run() 
be/src/load/memtable/memtable_flush_executor.cpp:100:5
   ```
   
   **Allocated by thread T640 (brpc_heavy, stream-load ingest path):**
   
   ```
       #1 doris::RowsetFactory::create_empty_group_rowset_writer(...) 
be/src/storage/rowset/rowset_factory.cpp:100
       #2 doris::GroupRowsetBuilder::init() 
be/src/storage/rowset_builder.cpp:570:5
       #4 doris::DeltaWriter::write(...) 
be/src/load/delta_writer/delta_writer.cpp:177:9
      #15 doris::PInternalService::tablet_writer_add_block ... 
internal_service.cpp:526
   ```
   
   On the suggested focused rerun around #66899/#66191: agreed it would cleanly 
separate "coverage" from "timing change", but since neither PR modified the 
lifetime code and the fix does not depend on that attribution, I'll skip the 
bisection unless a maintainer wants it.
   
   A fix is ready following the recommended approach: `SharedMemtable` owns 
`std::shared_ptr<SegmentAllocatedLsnMap>` captured at submission, insert/remove 
through the map directly, non-null map standing in for `need_allocated_lsn()`, 
plus ASAN unit tests covering (a) the last token/writer owner released while a 
group flush task finishes, (b) a queued subtask running after its weak token 
expired, and (c) cancellation, with LSN-entry cleanup asserted on the success 
and flush-error paths. Verified in both directions under ASAN: without the fix 
the new tests abort with this exact use-after-free; with the fix the 
memtable-flush-executor tests pass 8/8. PR to follow shortly.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to