From nobody Mon Jun 8 19:46:39 2026 Received: from mail-vs1-f42.google.com (mail-vs1-f42.google.com [209.85.217.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2027250C06 for ; Wed, 27 May 2026 05:59:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.217.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779861568; cv=none; b=Q44tJ3qvsC7WceI0Cot/K834QS9Kv/QXqNaQ/qKed70sAymzliXEdRuGdCKi4exxXDC7IfCIpyJTVh5TezomIf444psMsmeuGPNd+8QCbJJnlR9blwLNexhjS06axnS0/yjDMFatsxtsiNvvxdr/cI6ztSK0Ii2dFJbtdOjwMDQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779861568; c=relaxed/simple; bh=l7E2bWhXWUwAl5QYLYAGKRuycBFteFirmB18b0PN7zs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=OQVDLw0y9q2roBMZUJvlS/avk9UOuf8VK33OOLK8lgcDKO7YThegiHGHQfTdooo8OFO/QI2T/vOgDqkeOKlwe510kg3FC6TA6sKy6F6j2XYAcHGy+YJgjplvwi/lbsmcn7iZePFJ0Do5IXy3Jk5ELIq5SNXGh5029cQwv8a3cRU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=f1G94Cz2; arc=none smtp.client-ip=209.85.217.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="f1G94Cz2" Received: by mail-vs1-f42.google.com with SMTP id ada2fe7eead31-63145ce291bso8829030137.0 for ; Tue, 26 May 2026 22:59:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779861565; x=1780466365; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=bzTGn9hr6uH1iCygCUxbYWLObtb15WQO/tFO/Zj+W+8=; b=f1G94Cz2jeVzJpmwb/9DPTtwmneLuCqOwrw5kUL0Mv4Mtpic2SW5gk8djpkKFT7q8P skeOwyN+6k65EO60vIKQZgr3mqqYZW5bmsuQwKcKER6MYTaNsG2ZZ5RW4vOLKvE8pRI+ Gg3WIMtceddBMFvMIodjtNr7Wmfjt6Sl5xc7yjYSXdjOxpspQbTAHqZttiq+73K1htGO dl10RpazSk/xm8wZs/F++JXZSZcvRLf8zzRre3BYVp6bQ7JOhoxD9R4phoS8RMiRlrGP 2vGqIkP5tiUJoYPUpYOkGseBIK3zzDvAxcDCrmmkmdvNFpj+HPnrqgUy7Xo3Y0uHMLut CNmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779861565; x=1780466365; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=bzTGn9hr6uH1iCygCUxbYWLObtb15WQO/tFO/Zj+W+8=; b=mbb1/ZEFwXv7MA6EZXTXo57kJH4fLLkpcxAW+bedWy5es4wr35PaONTD7CyMBN0Cce nXjdYDLKNNrygZfCcncJMuQQCCYZAHJgD4kW+kl3WF7zruqiPLEVIHfnwwrQSPnrSHQY vBB/Lyx1GoI8Qml3n2FcjEKOX8VJtjfPwQFPv41pyWtkUtwD/Xp/BHjHSuXT+lY69wJx OpehOnePmuoy2V+Z4NAVJH0qYi0qRb0pu7Dt4wbdu16P36CqMdi4ouxFsJtRSfxt+jL1 x/hvax5cBC4i73O8sTkHyOQq92mb3rUZhPkeEdsVuqLNeoVjdv1NSa4zY8YygAdlwvX9 VyAQ== X-Forwarded-Encrypted: i=1; AFNElJ/JPKeGdGE3s8VI5/n3sVru/Ng80D7s5qqKdr5P0B3wf4a1GOIPU6Zu//++VnZQKHiC8AExzDtpkflyffI=@vger.kernel.org X-Gm-Message-State: AOJu0YzrBVh3RpwbDSGj7XT3eeAxrx6AZwfT/XHBDYbmalwyWh3xvWp5 NHiT8rRhNHERkTkmgAmsGN0+Ttu21+mgtOZbsSZv8mnZYuQvQ2h7qDmQ X-Gm-Gg: Acq92OFlGLK6L2w7CEyhdRJtD1HXx7Ca2Q8RsGl3a/zzaBH4FCaAr2t7XoQ4tpPX12G Zk2RrFvaukDdormRHu0w4KtKC781zP+sd68NJ08cgHuszjnQqKAtC4quFwe8yUt/tBi4yB+1DWH 8cLr9ydmcfwiqRbWw+243fNPolos5dNlIU0Z2Y/Oz1bOuVzZWdzONESQcT4ER614DLZu2bsH5Cw nV2rlaQxOT1++UCXSdTsaPjS22pGw95wEZIEarKo9Lf+KfmRpXn368Sd8bO3KFx28KbsFlnvM+s ULiW/ZIFJWACmTse79YUum4af/jwV5EWqVChJjSSLVfp6xe3nhbO6Ca7KsGQghnXjmG4Tpj3p6G WpryLYa512+3tg9JQy7WV7tRvIKjJZmDxDJCRGREcYiWQJ3+amVJZP1CeMAo9lwpwcuKYg8oh0b 95K+CqRp3y2ZFHYeqdLvTwL5izPwT7CfdIiHL1uHNV6uYimt9ltnFm01Gg1Zm95sI= X-Received: by 2002:a05:6102:809f:b0:632:a084:c0f7 with SMTP id ada2fe7eead31-67c85b3e92dmr10373841137.17.1779861565438; Tue, 26 May 2026 22:59:25 -0700 (PDT) Received: from syssplab.cs.fiu.edu (nat1.cs.fiu.edu. [131.94.134.89]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-961d388f339sm1537950241.12.2026.05.26.22.59.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2026 22:59:24 -0700 (PDT) From: Chao Shi To: Keith Busch , Jens Axboe , Christoph Hellwig , Sagi Grimberg Cc: Chaitanya Kulkarni , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Sungwoo Kim , Dave Tian , Weidong Zhu Subject: [PATCH] nvme: bound the freeze drain in passthrough commands Date: Wed, 27 May 2026 01:59:23 -0400 Message-ID: <20260527055923.456769-1-coshi036@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" nvme_passthru_start() drains in-flight I/O via the unbounded nvme_wait_freeze() before submitting a command with command-set effects (Format NVM, Sanitize, Namespace Management, vendor unique). If a completion is silently dropped or the device hangs, the calling task wedges with ctrl->scan_lock and ctrl->subsys->lock held, fanning out into hung-task reports on any concurrent open/close/passthru on the same controller: INFO: task syz-executor:NNNN blocked for more than 123 seconds. nvme_wait_freeze+0x82/0x100 nvme_passthru_start drivers/nvme/host/core.c:1249 [inline] nvme_submit_user_cmd+0x1ee/0x3d0 drivers/nvme/host/ioctl.c:189 The other freeze-drain sites (pci shutdown, tcp/rdma reset) already bound the wait with nvme_wait_freeze_timeout(NVME_IO_TIMEOUT). Apply it here too; on timeout, unwind the freeze and return -EBUSY (or NVME_SC_INTERNAL on the nvmet path) instead of submitting the command. Found by FuzzNvme(Syzkaller with FEMU fuzzing framework). Acked-by: Sungwoo Kim Acked-by: Dave Tian Acked-by: Weidong Zhu Signed-off-by: Chao Shi --- drivers/nvme/host/core.c | 26 ++++++++++++++++++++------ drivers/nvme/host/ioctl.c | 7 ++++++- drivers/nvme/host/nvme.h | 3 ++- drivers/nvme/target/passthru.c | 7 ++++++- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 7bf228df6001..575f98b9a6cc 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1232,23 +1232,37 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, st= ruct nvme_ns *ns, u8 opcode) } EXPORT_SYMBOL_NS_GPL(nvme_command_effects, "NVME_TARGET_PASSTHRU"); =20 -u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opc= ode) +int nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opc= ode, + u32 *effects) { - u32 effects =3D nvme_command_effects(ctrl, ns, opcode); + *effects =3D nvme_command_effects(ctrl, ns, opcode); =20 /* * For simplicity, IO to all namespaces is quiesced even if the command - * effects say only one namespace is affected. + * effects say only one namespace is affected. Bound the drain wait so + * a stuck I/O cannot wedge the passthrough caller (and any task on the + * scan_lock or subsys lock) indefinitely; the other in-tree callers of + * the freeze drain (pci shutdown, tcp/rdma reset) already use this same + * NVME_IO_TIMEOUT bound. */ - if (effects & NVME_CMD_EFFECTS_CSE_MASK) { + if (*effects & NVME_CMD_EFFECTS_CSE_MASK) { mutex_lock(&ctrl->scan_lock); mutex_lock(&ctrl->subsys->lock); nvme_mpath_start_freeze(ctrl->subsys); nvme_mpath_wait_freeze(ctrl->subsys); nvme_start_freeze(ctrl); - nvme_wait_freeze(ctrl); + if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) { + dev_warn(ctrl->device, + "I/O did not drain in %u seconds; aborting passthrough\n", + nvme_io_timeout); + nvme_unfreeze(ctrl); + nvme_mpath_unfreeze(ctrl->subsys); + mutex_unlock(&ctrl->subsys->lock); + mutex_unlock(&ctrl->scan_lock); + return -EBUSY; + } } - return effects; + return 0; } EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, "NVME_TARGET_PASSTHRU"); =20 diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index a9c097dacad6..762458a23b38 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -186,7 +186,12 @@ static int nvme_submit_user_cmd(struct request_queue *= q, bio =3D req->bio; ctrl =3D nvme_req(req)->ctrl; =20 - effects =3D nvme_passthru_start(ctrl, ns, cmd->common.opcode); + ret =3D nvme_passthru_start(ctrl, ns, cmd->common.opcode, &effects); + if (ret) { + if (bio) + blk_rq_unmap_user(bio); + goto out_free_req; + } ret =3D nvme_execute_rq(req, false); if (result) *result =3D le64_to_cpu(nvme_req(req)->result.u64); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 9a5f28c5103c..665d75de044e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -1211,7 +1211,8 @@ static inline void nvme_auth_revoke_tls_key(struct nv= me_ctrl *ctrl) {}; =20 u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode); -u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opc= ode); +int nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opc= ode, + u32 *effects); int nvme_execute_rq(struct request *rq, bool at_head); void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 eff= ects, struct nvme_command *cmd, int status); diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index 67c423a8b052..7b97bfc1ace6 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -220,7 +220,12 @@ static void nvmet_passthru_execute_cmd_work(struct wor= k_struct *w) u32 effects; int status; =20 - effects =3D nvme_passthru_start(ctrl, ns, req->cmd->common.opcode); + status =3D nvme_passthru_start(ctrl, ns, req->cmd->common.opcode, &effect= s); + if (status) { + nvmet_req_complete(req, NVME_SC_INTERNAL); + blk_mq_free_request(rq); + return; + } status =3D nvme_execute_rq(rq, false); if (status =3D=3D NVME_SC_SUCCESS && req->cmd->common.opcode =3D=3D nvme_admin_identify) { --=20 2.43.0