Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jens Axboe <axboe@kernel.dk>, Sasha Levin <sashal@kernel.org>,
	io-uring@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 7.0] io_uring: defer linked-timeout chain splice out of hrtimer context
Date: Wed, 20 May 2026 07:19:21 -0400	[thread overview]
Message-ID: <20260520111944.3424570-49-sashal@kernel.org> (raw)
In-Reply-To: <20260520111944.3424570-1-sashal@kernel.org>

From: Jens Axboe <axboe@kernel.dk>

[ Upstream commit 49ae66eb8c27375075ffa308cfd4bf25af335d41 ]

io_link_timeout_fn() is the hrtimer callback that fires when a linked
timeout expires. It currently calls io_remove_next_linked(prev) under
ctx->timeout_lock to splice the timeout request out of the link chain.
This is the only chain-mutation site that runs without ctx->uring_lock,
because hrtimer callbacks cannot take a mutex. Defer the splicing until
the task_work callback.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit Message Forensics
Record: subsystem `io_uring`; action verb `defer`; intent is to move
linked-timeout chain splicing out of `io_link_timeout_fn()` hrtimer
context and into task_work.

Record: tags found only `Signed-off-by: Jens Axboe <axboe@kernel.dk>`.
No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc: stable`,
or external `Link:` in the upstream commit.

Record: the body describes a locking bug: `io_link_timeout_fn()` mutates
the linked request chain under `ctx->timeout_lock` but without
`ctx->uring_lock`; hrtimer callbacks cannot take the mutex, so mutation
is deferred to task_work.

Record: this is a real hidden bug fix despite not saying “fix”: it
corrects an unsynchronized linked-list mutation in an hrtimer callback.

## Phase 2: Diff Analysis
Record: one file changed, `io_uring/timeout.c`, 14 insertions and 2
deletions. Modified functions: `__io_disarm_linked_timeout()`,
`io_req_task_link_timeout()`, `io_link_timeout_fn()`. Scope is single-
file surgical locking/race fix.

Record: before, `io_link_timeout_fn()` called
`io_remove_next_linked(prev)` directly from hrtimer context under only
`timeout_lock`. After, the timer claims the timeout, stores
`timeout->prev`, and queues task_work; `io_req_task_link_timeout()` then
splices `req` out of `prev->link` if the normal completion path did not
already do so.

Record: `__io_disarm_linked_timeout()` now detects `timeout->head ==
NULL`, meaning the timer already claimed the timeout, and avoids
cancel/list removal in that race.

Record: bug category is synchronization/race on linked request chain
mutation. Fix quality is good but series-sensitive: patch 3/3
(`a65855ec34aed`) is needed to keep `io_kill_timeouts()` walking chains
under `uring_lock` after this patch changes where splicing happens.

## Phase 3: Git History Investigation
Record: blame shows the relevant linked-timeout code and
`io_remove_next_linked()` originated mainly from `59915143e89f`
(“io_uring: move timeout opcodes and handling into its own file”), first
contained around `v6.0-rc1`; later timeout-lock changes include
`020b40f35624`, and `__io_disarm_linked_timeout()` changes include
`78967aabf613`, first around `v6.16-rc1`.

Record: no `Fixes:` tag exists, so there was no tagged introducer to
follow.

Record: recent history shows this is patch 2/3 in a linked-request
locking series:
`20c39819a276` locks `io_wq_free_work()` chain walking,
`49ae66eb8c27` defers linked-timeout splicing,
`a65855ec34ae` keeps `uring_lock` across `io_kill_timeouts()`.

Record: Jens Axboe is listed in `MAINTAINERS` as the `IO_URING`
maintainer and authored the commit.

## Phase 4: Mailing List And External Research
Record: `b4 dig -c 49ae66eb8c27` found the lore submission at
`https://patch.msgid.link/20260511182217.226763-3-axboe@kernel.dk`.

Record: `b4 dig -a` found only v1 of the 3-patch series. `b4 dig -w`
showed recipients were Jens Axboe and `io-uring@vger.kernel.org`.

Record: the saved mbox contains the cover letter “[PATCHSET 0/3] Linked
request fix”, stating chain iteration must hold either `uring_lock` or
`timeout_lock`, and modification should be buttoned up. No replies,
NAKs, review tags, or stable nominations were present in the mbox.

Record: direct `WebFetch` of lore and stable search pages was blocked by
Anubis, so no web-side stable discussion could be verified.

## Phase 5: Code Semantic Analysis
Record: key functions are `io_link_timeout_fn()`,
`io_req_task_link_timeout()`, `__io_disarm_linked_timeout()`, and
`io_remove_next_linked()`.

Record: call/reachability tracing verified `IORING_OP_LINK_TIMEOUT` uses
`io_link_timeout_prep()` in `io_uring/opdef.c`; prep installs
`io_link_timeout_fn()` as the hrtimer callback, and linked timeouts are
queued on `ctx->ltimeout_list`.

Record: task_work runners in `io_uring/tw.c` execute callbacks while
holding `ctx->uring_lock` in normal, fallback, and local-work paths.
This verifies the deferred splice runs in a mutex-protected context.

Record: similar pattern search found the hrtimer callback was the unique
changed direct chain mutation site in this diff; the related series
covers other chain walking gaps.

## Phase 6: Stable Tree Analysis
Record: `git merge-base --is-ancestor` verified the old timeout split
commit exists in `v6.19.14` and `v6.6.140`; the candidate itself is not
in `v7.0.9` or `v6.19.14`.

Record: `git show`/`rg` verified the buggy `io_link_timeout_fn()`
pattern exists in `v7.0.9`, `v6.19.14`, `v6.15`, `v6.12.90`, `v6.6.140`,
and in older `v5.15` under `fs/io_uring.c`.

Record: `git diff 49ae^..49ae | git apply --check` succeeded on the
current `v7.0.9` checkout. Older trees have API/path differences such as
task_work signature and `spin_lock` vs `raw_spin_lock`, so they need
manual backporting.

## Phase 7: Subsystem Context
Record: subsystem is `io_uring`, a core async I/O userspace API.
Criticality is IMPORTANT: not universal like MM/VFS, but reachable from
userspace and widely used.

Record: `git log origin/master --oneline -20 -- io_uring` shows high
activity, including this linked-request locking series and other recent
fixes.

## Phase 8: Impact And Risk
Record: affected users are systems using io_uring linked requests with
`IORING_OP_LINK_TIMEOUT`.

Record: trigger is a timing race between linked-timeout hrtimer expiry
and other linked-chain completion/cancel paths; this is reachable from
userspace via io_uring submissions.

Record: verified failure class is unsynchronized linked-list/request-
chain mutation. No crash report was verified, but the protected object
is request-chain state, so the stability risk is request chain
corruption, wrong cancellation/completion, or follow-on memory lifetime
bugs.

Record: benefit is high for affected io_uring users because it closes a
real locking gap in request lifetime/chain handling. Risk is low-medium:
the patch is small, but should be backported with the adjacent locking
fixes, especially `a65855ec34aed`.

## Phase 9: Final Synthesis
Record: evidence for backporting: real race fix, userspace-reachable
io_uring path, single-file 16-line patch, authored by subsystem
maintainer, applies cleanly to `v7.0.9`, and the buggy pattern exists
across active stable/LTS tags checked.

Record: evidence against/concerns: no reporter/test tag, no explicit
stable tag, no verified crash trace, and the commit is part of a 3-patch
locking series; backporting only this patch without the follow-up
cancel-path lock change can leave the locking story incomplete.

Record: stable rules: obviously correct by code inspection with the
series context; fixes a real synchronization bug; important because it
affects request-chain mutation in a userspace API; small and contained;
no new feature/API; applies cleanly to `v7.0.9`, with older trees
needing backport adjustment.

Record: no automatic exception category applies; this is not a device
ID, quirk, DT, build, or documentation fix.

## Verification
- [Phase 1] `git show -s` confirmed subject, body, author, and absence
  of tags beyond Jens’s SOB.
- [Phase 2] `git show --patch 49ae66eb8c27` confirmed
  `io_uring/timeout.c` only, 14 insertions/2 deletions.
- [Phase 3] `git blame` confirmed relevant code history; `git describe
  --contains` placed `59915143e89f` around `v6.0-rc1` and `78967aabf613`
  around `v6.16-rc1`.
- [Phase 3] `git log` confirmed related commits `20c39819a276` and
  `a65855ec34ae`.
- [Phase 4] `b4 dig` found the exact patch submission and v1 3-patch
  series; saved mbox showed no review replies or stable nomination.
- [Phase 5] `rg` and `git show` traced `IORING_OP_LINK_TIMEOUT` prep,
  hrtimer setup, task_work execution, and task_work locking.
- [Phase 6] stable tag checks verified the buggy pattern exists in
  checked stable/LTS tags; `git apply --check` succeeded on current
  `v7.0.9`.
- [Phase 7] `MAINTAINERS` verified Jens Axboe maintains `IO_URING`.
- [Phase 8] failure mode is verified as a locking/race bug; concrete
  crash symptoms are UNVERIFIED.

The commit should be backported, preferably together with the adjacent
linked-request locking series commits needed for a complete invariant.

**YES**

 io_uring/timeout.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/io_uring/timeout.c b/io_uring/timeout.c
index e3815e3465dde..4ee1c21e1b15f 100644
--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -245,6 +245,10 @@ static struct io_kiocb *__io_disarm_linked_timeout(struct io_kiocb *req,
 	struct io_timeout *timeout = io_kiocb_to_cmd(link, struct io_timeout);
 
 	io_remove_next_linked(req);
+
+	/* If this is NULL, then timer already claimed it and will complete it */
+	if (!timeout->head)
+		return NULL;
 	timeout->head = NULL;
 	if (hrtimer_try_to_cancel(&io->timer) != -1) {
 		list_del(&timeout->list);
@@ -328,6 +332,14 @@ static void io_req_task_link_timeout(struct io_tw_req tw_req, io_tw_token_t tw)
 	int ret;
 
 	if (prev) {
+		/*
+		 * splice the linked timeout out of prev's chain if the regular
+		 * completion path didn't already do it.
+		 */
+		if (prev->link == req)
+			prev->link = req->link;
+		req->link = NULL;
+
 		if (!tw.cancel) {
 			struct io_cancel_data cd = {
 				.ctx		= req->ctx,
@@ -362,10 +374,10 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
 
 	/*
 	 * We don't expect the list to be empty, that will only happen if we
-	 * race with the completion of the linked work.
+	 * race with the completion of the linked work. Splice of prev is
+	 * done in io_req_task_link_timeout(), if needed.
 	 */
 	if (prev) {
-		io_remove_next_linked(prev);
 		if (!req_ref_inc_not_zero(prev))
 			prev = NULL;
 	}
-- 
2.53.0


  parent reply	other threads:[~2026-05-20 11:20 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-20 11:18 [PATCH AUTOSEL 7.0-6.12] HID: logitech-hidpp: Add support for newer Bluetooth keyboards Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0] drm/amdgpu: remove deadlocks from amdgpu_userq_pre_reset Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] ALSA: sparc/dbri: add missing fallthrough Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.6] docs: cgroup-v1: Update charge-commit section Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] drm/panel: feiyang-fy07024di26a30d: return display-on error Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.6] ALSA: usb-audio: Add iface reset and delay quirk for TTGK Technology USB-C Audio Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] selftests/cgroup: Fix cg_read_strcmp() empty string comparison Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.1] smb: client: Zero-pad short GSS session keys per MS-SMB2 Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] HID: magicmouse: Prevent out-of-bounds (OOB) read during DOUBLE_REPORT_ID Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0] smb: client: avoid integer overflow in SMB2 READ length check Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] libceph: Fix unnecessarily high ceph_decode_need() for uniform bucket Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.6] ALSA: hda/realtek: fix mic boost on Framework PTL Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.6] io_uring: hold uring_lock when walking link chain in io_wq_free_work() Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.15] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.12] KVM: arm64: nv: Consider the DS bit when translating TCR_EL2 Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0] docs: hwmon: sy7636a: fix temperature sysfs attribute name Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0] ALSA: hda/realtek: ALC269 fixup for Lenovo Yoga Pro 7 15ASH111 audio Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.6] ipv6: Implement limits on extension header parsing Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.12] net: usb: cdc_ncm: add Apple Mac USB-C direct networking quirk Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.15] net: usb: r8152: add TRENDnet TUC-ET2G v2.0 Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] i2c: dev: prevent integer overflow in I2C_TIMEOUT ioctl Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] powerpc/vmx: avoid KASAN instrumentation in enter_vmx_ops() for kexec Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-6.18] ALSA: usb-audio: add min_mute quirk for Razer Nommo V2 X Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] wifi: libertas: fix integer underflow in process_cmdrequest() Sasha Levin
2026-05-20 20:41   ` James Cameron
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] HID: mcp2221: fix OOB write in mcp2221_raw_event() Sasha Levin
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0] io_uring/wait: honour caller's time namespace for IORING_ENTER_ABS_TIMER Sasha Levin
2026-05-20 11:40   ` Jens Axboe
2026-05-20 11:18 ` [PATCH AUTOSEL 7.0-5.10] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] HID: elan: Add support for ELAN SB974D touchpad Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] media: qcom: camss: avoid format string warning Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] HID: i2c-hid: add reset quirk for BLTP7853 touchpad Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] ALSA: hda/realtek: Limit mic boost on Positivo DN50E Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] Documentation: kvm: update links in the references section of AMD Memory Encryption Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] scsi: scsi_dh_alua: Increase default ALUA timeout to maximum spec value Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.1] HID: google: hammer: stop hardware on devres action failure Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] ALSA: doc: cs35l56: Update path to HDA driver source Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] Bluetooth: hci_uart: Fix NULL deref in recv callbacks when priv is uninitialized Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0] ALSA: hda/realtek: Add mute LED fixup for HP Pavilion 15-cs1xxx Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] btrfs: fix check_chunk_block_group_mappings() to iterate all chunk maps Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.15] ALSA: usb-audio: Add quirk flags for AlphaTheta EUPHONIA Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] powerpc/g5: Enable all windfarms by default Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] ALSA: hda/realtek: Add codec SSID quirk for Lenovo Yoga Pro 9 16IMH9 Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] tools/ynl: add missing uapi header deps in Makefile.deps Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] fbdev: ipu-v3: clean up kernel-doc warnings Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.6] ASoC: amd: yc: Add DMI quirk for MSI Bravo 15 C7VE Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.1] powerpc/pasemi: Drop redundant res assignment Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] cgroup/cpuset: move PF_EXITING check before __GFP_HARDWALL in cpuset_current_node_allowed() Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] drm/amd/ras: Fix CPER ring debugfs read overflow Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.15] scsi: smartpqi: Silence a recursive lock warning Sasha Levin
2026-05-20 11:19 ` Sasha Levin [this message]
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] io_uring: validate user-controlled cq.head in io_cqe_cache_refill() Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] platform/x86: asus-nb-wmi: add DMI quirk for ASUS Zenbook Duo UX8407AA Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] powerpc/pseries/htmdump: Free the global buffers in htmdump module exit Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.6] HID: sony: add missing size validation for SMK-Link remotes Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.15] HID: ft260: validate i2c input report length Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0] io_uring: hold uring_lock across io_kill_timeouts() in cancel path Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0] platform/x86: hp-wmi: Add support for Victus 16-r0xxx (8BC2) Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] i2c: acpi: Add ELAN0678 to i2c_acpi_force_100khz_device_ids Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] KVM: VMX: introduce module parameter to disable CET Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] iommu/amd: Use maximum Event log buffer size when SNP is enabled on Family 0x19 Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-5.10] ALSA: usb-audio: add clock quirk for Motu 1248 Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.18] workqueue: Release PENDING in __queue_work() drain/destroy reject path Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0] ASoC: sdw_utils: avoid the SDCA companion function not supported failure Sasha Levin
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0] Documentation: security-bugs: do not systematically Cc the security team Sasha Levin
2026-05-20 13:07   ` Jonathan Corbet
2026-05-20 11:19 ` [PATCH AUTOSEL 7.0-6.12] io_uring/fdinfo: translate SqThread PID through caller's pid_ns Sasha Levin

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=20260520111944.3424570-49-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=io-uring@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    /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