Skip to content

[Backport][main to 0.9] | fix(iouring): plug UAF on _async_io early returns (#1569) - #1619

Merged
lihuiba merged 3 commits into
release/0.9from
backport-pr-8e97a7737773dc6e632e61d6fe45e5b998ff33ec-0.9
Aug 21, 2026
Merged

[Backport][main to 0.9] | fix(iouring): plug UAF on _async_io early returns (#1569)#1619
lihuiba merged 3 commits into
release/0.9from
backport-pr-8e97a7737773dc6e632e61d6fe45e5b998ff33ec-0.9

Conversation

@photonlibos

Copy link
Copy Markdown
Collaborator

fix(iouring): plug UAF on _async_io early returns (#1569)

The stack-allocated ioCtx/timer_ctx could go out of scope while
their CQEs were still in flight, on three early-return paths:
timer/cancel SQE allocation failure and the cancel branch itself.
Introduce an ioCtx::done flag set by reap_events on the final CQE;
neutralize the queued first SQE with a NOP, and wait on the done
flags before returning. A generation counter unblocks the waiters
once reset() (fork) drops the old ring, whose CQEs never arrive.
Add regression test test-iouring-uaf. Fixes #1270.
Generated by Backport Auto PR, by cherry-pick related commits.

Please review and decide whether to merge or close this backport PR.

Conflicts

Cherry-pick produced conflicts. Conflict markers are committed as-is; please resolve them manually before merging.

  • 8e97a77: io/iouring-wrapper.cpp,io/test/CMakeLists.txt

Dropped new files

The following new files introduced by cherry-pick were dropped because they don't exist in release/0.9:

  • io/test/test-iouring-uaf.cpp

jfeng18 and others added 2 commits August 19, 2026 11:52
The stack-allocated ioCtx/timer_ctx could go out of scope while
their CQEs were still in flight, on three early-return paths:
timer/cancel SQE allocation failure and the cancel branch itself.
Introduce an ioCtx::done flag set by reap_events on the final CQE;
neutralize the queued first SQE with a NOP, and wait on the done
flags before returning. A generation counter unblocks the waiters
once reset() (fork) drops the old ring, whose CQEs never arrive.
Add regression test test-iouring-uaf. Fixes #1270.
@photonlibos photonlibos added bugfix A PR that should be back-ported to prior release branches (release/*) needs-manual-merge labels Aug 19, 2026
This engine still has the pre-refactoring shape of main, so the fix had
to be re-expressed rather than applied.

- io/iouring-wrapper.cpp: set ctx->done in the CQE loop of
  wait_and_fire_events(), which here is separate from wait_for_events()
  and has no is_event handling, so main's unified reap_events() block is
  not imported. The flag is set right after ctx->res, guarded by
  !IORING_CQE_F_MORE, instead of at the end of the loop body: the
  -ECANCELED branches of this branch come first and `continue`, and both
  io_ctx and timer_ctx report -ECANCELED once a cancellation takes
  effect, so the end of the body is unreachable for exactly the contexts
  the new wait loops in _async_io block on. Verified by experiment: with
  the flag at the end, iouring_uaf.interrupt_storm hangs.
- io/iouring-wrapper.cpp: drop the try_submit() call the cherry-pick
  brought into the cancel path. That helper does not exist here and
  cannot be ported, as it is gated on m_args.eager_submit, which this
  branch has no equivalent of; submission stays lazy, driven by
  wait_and_fire_events(), as it was before. Note that git reported no
  conflict for this hunk, so it would have been a build break.
- io/test/CMakeLists.txt: keep the signalfdboom target of this branch and
  register test-iouring-uaf with add_executable/target_link_libraries/
  add_test under the existing `if (NOT APPLE)`, since photon_add_test()
  and `if (LINUX)` come from main's test-helper refactoring.
- io/test/test-iouring-uaf.cpp: restore the regression test, which the
  backport tooling dropped as a new file while still referencing it from
  CMakeLists.txt. It needs no adaptation.

Validated: test-iouring-uaf passes all 4 cases, including the interrupt
storms that drive the cancel path over ~1200 rounds; test-iouring (10)
and test-fork (5) pass, the latter covering ForkTest.Iouring, i.e. the
reset()/generation path that releases the waiters.
@Coldwings
Coldwings marked this pull request as ready for review August 20, 2026 04:23
@lihuiba
lihuiba merged commit dd236e9 into release/0.9 Aug 21, 2026
30 checks passed
@photonlibos
photonlibos deleted the backport-pr-8e97a7737773dc6e632e61d6fe45e5b998ff33ec-0.9 branch August 21, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix A PR that should be back-ported to prior release branches (release/*)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants