Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nvmet: clamp the last ANA group index against the real array size
@ 2026-11-06  6:40 Yuehong Wu
  2026-11-06  7:03 ` Yuehong Wu
  2026-11-12 21:21 ` Christoph Hellwig
  0 siblings, 2 replies; 4+ messages in thread
From: Yuehong Wu @ 2026-11-06  6:40 UTC (permalink / raw)
  To: linux-nvme
  Cc: Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni, Keith Busch,
	Maurizio Lombardi, Mohamed Khalfella, Nitesh Shetty,
	Hannes Reinecke, Randy Dunlap, Aurelien Aptel, Nilay Shroff,
	Jesse Taube, Rongzheng Wang, Kees Cook, Rosen Penev, Guixin Liu,
	Qing Zhang, Eric Biggers, Julian Sun, Yu Zhang, linux-kernel

NVMET_MAX_ANAGRPS is the highest valid ANA group id, not the size of
nvmet_ana_group_enabled[]: the array has NVMET_MAX_ANAGRPS + 1 entries
and the controller advertises anagrpmax == NVMET_MAX_ANAGRPS.  Both
array_index_nospec() calls however pass NVMET_MAX_ANAGRPS as the size,
so for the last group the mask is 0 and the index quietly becomes 0:

 - nvmet_ana_groups_make_group() increments enabled[0] while the group
   keeps grpid == 128, so the later nvmet_ana_group_release() decrements
   enabled[128], which underflows to 0xffffffff.  The ANA log page then
   reports group 128 as inaccessible forever even though the configfs
   group no longer exists, and the increment on enabled[0] is never
   undone.

 - nvmet_ns_ana_grpid_store() accepts 128, stores 0 in ns->anagrpid and
   returns success, so the namespace silently stays in the default ANA
   group instead of the one the user asked for.

Both failures are silent, and they change what the target reports in its
ANA log page, which is what a host uses to select paths.

Pass the real array size in both calls, so the masking is kept but the
last group is no longer folded onto index 0.

Fixes: 20dc66f2d76b ("nvme: prevent potential spectre v1 gadget")
Cc: stable@vger.kernel.org
Signed-off-by: Yuehong Wu <wuyuehong@cmss.chinamobile.com>
---
Verified with nvme-loop in QEMU/KVM on 7.3.0-next-20261027, with two
kernels built from the same tree and differing only in these two lines
(no instrumentation):

 - before the patch, a group created as ports/1/ana_groups/128 is absent
   from the ANA log page (ngrps=1) even though configfs accepted it, and
   it is reported as expected afterwards (ngrps=2, group 128 optimized);
 - 128 written to a namespace ana_grpid reads back as 0 before the patch
   and as 128 after it, and the namespace is accounted to group 128;
 - removing the group again adds a phantom group 128 (state inaccessible,
   0 namespaces) to the ANA log page before the patch, and leaves no
   trace after it, even when creating and removing it repeatedly.

 drivers/nvme/target/configfs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 8aea64d..48d3f68 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -701,7 +701,7 @@ static ssize_t nvmet_ns_ana_grpid_store(struct config_item *item,
 
 	down_write(&nvmet_ana_sem);
 	oldgrpid = ns->anagrpid;
-	newgrpid = array_index_nospec(newgrpid, NVMET_MAX_ANAGRPS);
+	newgrpid = array_index_nospec(newgrpid, NVMET_MAX_ANAGRPS + 1);
 	nvmet_ana_group_enabled[newgrpid]++;
 	ns->anagrpid = newgrpid;
 	nvmet_ana_group_enabled[oldgrpid]--;
@@ -2074,7 +2074,7 @@ static struct config_group *nvmet_ana_groups_make_group(
 	grp->grpid = grpid;
 
 	down_write(&nvmet_ana_sem);
-	grpid = array_index_nospec(grpid, NVMET_MAX_ANAGRPS);
+	grpid = array_index_nospec(grpid, NVMET_MAX_ANAGRPS + 1);
 	nvmet_ana_group_enabled[grpid]++;
 	up_write(&nvmet_ana_sem);
 
-- 
2.43.0




^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-11-12 21:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-06  6:40 [PATCH] nvmet: clamp the last ANA group index against the real array size Yuehong Wu
2026-11-06  7:03 ` Yuehong Wu
2026-11-06 13:47   ` Andrew Stellman
2026-11-12 21:21 ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox