linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray
@ 2025-11-27  1:39 Fengnan Chang
  2025-11-27  1:39 ` [PATCH v2 1/2] " Fengnan Chang
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Fengnan Chang @ 2025-11-27  1:39 UTC (permalink / raw)
  To: axboe, linux-block, ming.lei, hare, hch, yukuai3; +Cc: Fengnan Chang

From: Fengnan Chang <changfengnan@bytedance.com>

After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
an xarray instead of array to store hctx, but in poll mode, each time
in blk_mq_poll, we need use xa_load to find corresponding hctx, this
introduce some costs. In my test, xa_load may cost 3.8% cpu.

After revert previous change, eliminates the overhead of xa_load and can
result in a 3% performance improvement.

potentital use-after-free on q->queue_hw_ctx can be fixed by use rcu to
avoid, same as Yu Kuai did in [1].

[1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/

Fengnan Chang (2):
  blk-mq: use array manage hctx map instead of xarray
  blk-mq: fix potential uaf for 'queue_hw_ctx'

 block/blk-mq-tag.c     |  2 +-
 block/blk-mq.c         | 63 ++++++++++++++++++++++++++++--------------
 block/blk-mq.h         | 13 ++++++++-
 include/linux/blk-mq.h |  3 +-
 include/linux/blkdev.h |  2 +-
 5 files changed, 58 insertions(+), 25 deletions(-)


base-commit: 4941a17751c99e17422be743c02c923ad706f888
-- 
2.39.5 (Apple Git-154)


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

* [PATCH v2 1/2] blk-mq: use array manage hctx map instead of xarray
  2025-11-27  1:39 [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Fengnan Chang
@ 2025-11-27  1:39 ` Fengnan Chang
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Fengnan Chang @ 2025-11-27  1:39 UTC (permalink / raw)
  To: axboe, linux-block, ming.lei, hare, hch, yukuai3; +Cc: Fengnan Chang

From: Fengnan Chang <changfengnan@bytedance.com>

After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
an xarray instead of array to store hctx, but in poll mode, each time
in blk_mq_poll, we need use xa_load to find corresponding hctx, this
introduce some costs. In my test, xa_load may cost 3.8% cpu.

This patch revert previous change, eliminates the overhead of xa_load
and can result in a 3% performance improvement.

potential use-after-free on q->queue_hw_ctx can be fixed by use rcu to
avoid in next patch, same as Yu Kuai did in [1].

[1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/

Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
---
 block/blk-mq-tag.c     |  2 +-
 block/blk-mq.c         | 58 +++++++++++++++++++++++++++---------------
 block/blk-mq.h         |  2 +-
 include/linux/blk-mq.h |  3 ++-
 include/linux/blkdev.h |  2 +-
 5 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 5b664dbdf655..33946cdb5716 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -499,7 +499,7 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_tag_iter_fn *fn,
 	int srcu_idx;
 
 	/*
-	 * __blk_mq_update_nr_hw_queues() updates nr_hw_queues and hctx_table
+	 * __blk_mq_update_nr_hw_queues() updates nr_hw_queues and queue_hw_ctx
 	 * while the queue is frozen. So we can use q_usage_counter to avoid
 	 * racing with it.
 	 */
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d626d32f6e57..eed12fab3484 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -723,7 +723,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
 	 * If not tell the caller that it should skip this queue.
 	 */
 	ret = -EXDEV;
-	data.hctx = xa_load(&q->hctx_table, hctx_idx);
+	data.hctx = q->queue_hw_ctx[hctx_idx];
 	if (!blk_mq_hw_queue_mapped(data.hctx))
 		goto out_queue_exit;
 	cpu = cpumask_first_and(data.hctx->cpumask, cpu_online_mask);
@@ -3935,8 +3935,6 @@ static void blk_mq_exit_hctx(struct request_queue *q,
 			blk_free_flush_queue_callback);
 	hctx->fq = NULL;
 
-	xa_erase(&q->hctx_table, hctx_idx);
-
 	spin_lock(&q->unused_hctx_lock);
 	list_add(&hctx->hctx_list, &q->unused_hctx_list);
 	spin_unlock(&q->unused_hctx_lock);
@@ -3978,14 +3976,8 @@ static int blk_mq_init_hctx(struct request_queue *q,
 				hctx->numa_node))
 		goto exit_hctx;
 
-	if (xa_insert(&q->hctx_table, hctx_idx, hctx, GFP_KERNEL))
-		goto exit_flush_rq;
-
 	return 0;
 
- exit_flush_rq:
-	if (set->ops->exit_request)
-		set->ops->exit_request(set, hctx->fq->flush_rq, hctx_idx);
  exit_hctx:
 	if (set->ops->exit_hctx)
 		set->ops->exit_hctx(hctx, hctx_idx);
@@ -4374,7 +4366,7 @@ void blk_mq_release(struct request_queue *q)
 		kobject_put(&hctx->kobj);
 	}
 
-	xa_destroy(&q->hctx_table);
+	kfree(q->queue_hw_ctx);
 
 	/*
 	 * release .mq_kobj and sw queue's kobject now because
@@ -4518,26 +4510,44 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
 static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
 				     struct request_queue *q)
 {
-	struct blk_mq_hw_ctx *hctx;
-	unsigned long i, j;
+	int i, j, end;
+	struct blk_mq_hw_ctx **hctxs = q->queue_hw_ctx;
+
+	if (q->nr_hw_queues < set->nr_hw_queues) {
+		struct blk_mq_hw_ctx **new_hctxs;
+
+		new_hctxs = kcalloc_node(set->nr_hw_queues,
+				       sizeof(*new_hctxs), GFP_KERNEL,
+				       set->numa_node);
+		if (!new_hctxs)
+			return;
+		if (hctxs)
+			memcpy(new_hctxs, hctxs, q->nr_hw_queues *
+			       sizeof(*hctxs));
+		q->queue_hw_ctx = new_hctxs;
+		kfree(hctxs);
+		hctxs = new_hctxs;
+	}
 
 	for (i = 0; i < set->nr_hw_queues; i++) {
 		int old_node;
 		int node = blk_mq_get_hctx_node(set, i);
-		struct blk_mq_hw_ctx *old_hctx = xa_load(&q->hctx_table, i);
+		struct blk_mq_hw_ctx *old_hctx = hctxs[i];
 
 		if (old_hctx) {
 			old_node = old_hctx->numa_node;
 			blk_mq_exit_hctx(q, set, old_hctx, i);
 		}
 
-		if (!blk_mq_alloc_and_init_hctx(set, q, i, node)) {
+		hctxs[i] = blk_mq_alloc_and_init_hctx(set, q, i, node);
+		if (!hctxs[i]) {
 			if (!old_hctx)
 				break;
 			pr_warn("Allocate new hctx on node %d fails, fallback to previous one on node %d\n",
 					node, old_node);
-			hctx = blk_mq_alloc_and_init_hctx(set, q, i, old_node);
-			WARN_ON_ONCE(!hctx);
+			hctxs[i] = blk_mq_alloc_and_init_hctx(set, q, i,
+					old_node);
+			WARN_ON_ONCE(!hctxs[i]);
 		}
 	}
 	/*
@@ -4546,13 +4556,21 @@ static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
 	 */
 	if (i != set->nr_hw_queues) {
 		j = q->nr_hw_queues;
+		end = i;
 	} else {
 		j = i;
+		end = q->nr_hw_queues;
 		q->nr_hw_queues = set->nr_hw_queues;
 	}
 
-	xa_for_each_start(&q->hctx_table, j, hctx, j)
-		blk_mq_exit_hctx(q, set, hctx, j);
+	for (; j < end; j++) {
+		struct blk_mq_hw_ctx *hctx = hctxs[j];
+
+		if (hctx) {
+			blk_mq_exit_hctx(q, set, hctx, j);
+			hctxs[j] = NULL;
+		}
+	}
 }
 
 static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
@@ -4588,8 +4606,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 	INIT_LIST_HEAD(&q->unused_hctx_list);
 	spin_lock_init(&q->unused_hctx_lock);
 
-	xa_init(&q->hctx_table);
-
 	blk_mq_realloc_hw_ctxs(set, q);
 	if (!q->nr_hw_queues)
 		goto err_hctxs;
@@ -5168,7 +5184,7 @@ int blk_mq_poll(struct request_queue *q, blk_qc_t cookie,
 {
 	if (!blk_mq_can_poll(q))
 		return 0;
-	return blk_hctx_poll(q, xa_load(&q->hctx_table, cookie), iob, flags);
+	return blk_hctx_poll(q, q->queue_hw_ctx[cookie], iob, flags);
 }
 
 int blk_rq_poll(struct request *rq, struct io_comp_batch *iob,
diff --git a/block/blk-mq.h b/block/blk-mq.h
index c4fccdeb5441..80a3f0c2bce7 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -84,7 +84,7 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *
 							  enum hctx_type type,
 							  unsigned int cpu)
 {
-	return xa_load(&q->hctx_table, q->tag_set->map[type].mq_map[cpu]);
+	return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]];
 }
 
 static inline enum hctx_type blk_mq_get_hctx_type(blk_opf_t opf)
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index b25d12545f46..0795f29dd65d 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -1000,7 +1000,8 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
 }
 
 #define queue_for_each_hw_ctx(q, hctx, i)				\
-	xa_for_each(&(q)->hctx_table, (i), (hctx))
+	for ((i) = 0; (i) < (q)->nr_hw_queues &&			\
+	     ({ hctx = (q)->queue_hw_ctx[i]; 1; }); (i)++)
 
 #define hctx_for_each_ctx(hctx, ctx, i)					\
 	for ((i) = 0; (i) < (hctx)->nr_ctx &&				\
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 70b671a9a7f7..56328080ca09 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -493,7 +493,7 @@ struct request_queue {
 
 	/* hw dispatch queues */
 	unsigned int		nr_hw_queues;
-	struct xarray		hctx_table;
+	struct blk_mq_hw_ctx	**queue_hw_ctx;
 
 	struct percpu_ref	q_usage_counter;
 	struct lock_class_key	io_lock_cls_key;
-- 
2.39.5 (Apple Git-154)


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

* [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Fengnan Chang
  2025-11-27  1:39 ` [PATCH v2 1/2] " Fengnan Chang
@ 2025-11-27  1:39 ` Fengnan Chang
  2025-11-27  3:33   ` Ming Lei
                     ` (4 more replies)
  2025-11-27  2:47 ` [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Jens Axboe
  2025-11-27  2:49 ` Jens Axboe
  3 siblings, 5 replies; 13+ messages in thread
From: Fengnan Chang @ 2025-11-27  1:39 UTC (permalink / raw)
  To: axboe, linux-block, ming.lei, hare, hch, yukuai3; +Cc: Fengnan Chang

From: Fengnan Chang <changfengnan@bytedance.com>

This is just apply Kuai's patch in [1] with mirror changes.

blk_mq_realloc_hw_ctxs() will free the 'queue_hw_ctx'(e.g. undate
submit_queues through configfs for null_blk), while it might still be
used from other context(e.g. switch elevator to none):

t1					t2
elevator_switch
 blk_mq_unquiesce_queue
  blk_mq_run_hw_queues
   queue_for_each_hw_ctx
    // assembly code for hctx = (q)->queue_hw_ctx[i]
    mov    0x48(%rbp),%rdx -> read old queue_hw_ctx

					__blk_mq_update_nr_hw_queues
					 blk_mq_realloc_hw_ctxs
					  hctxs = q->queue_hw_ctx
					  q->queue_hw_ctx = new_hctxs
					  kfree(hctxs)
    movslq %ebx,%rax
    mov    (%rdx,%rax,8),%rdi ->uaf

This problem was found by code review, and I comfirmed that the concurrent
scenario do exist(specifically 'q->queue_hw_ctx' can be changed during
blk_mq_run_hw_queues()), however, the uaf problem hasn't been repoduced yet
without hacking the kernel.

Sicne the queue is freezed in __blk_mq_update_nr_hw_queues(), fix the
problem by protecting 'queue_hw_ctx' through rcu where it can be accessed
without grabbing 'q_usage_counter'.

[1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
---
 block/blk-mq.c         |  7 ++++++-
 block/blk-mq.h         | 11 +++++++++++
 include/linux/blk-mq.h |  2 +-
 include/linux/blkdev.h |  2 +-
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index eed12fab3484..0b8b72194003 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -4524,7 +4524,12 @@ static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
 		if (hctxs)
 			memcpy(new_hctxs, hctxs, q->nr_hw_queues *
 			       sizeof(*hctxs));
-		q->queue_hw_ctx = new_hctxs;
+		rcu_assign_pointer(q->queue_hw_ctx, new_hctxs);
+		/*
+		 * Make sure reading the old queue_hw_ctx from other
+		 * context concurrently won't trigger uaf.
+		 */
+		synchronize_rcu_expedited();
 		kfree(hctxs);
 		hctxs = new_hctxs;
 	}
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 80a3f0c2bce7..52852fab78f0 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -87,6 +87,17 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *
 	return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]];
 }
 
+static inline struct blk_mq_hw_ctx *queue_hctx(struct request_queue *q, int id)
+{
+	struct blk_mq_hw_ctx *hctx;
+
+	rcu_read_lock();
+	hctx = rcu_dereference(q->queue_hw_ctx)[id];
+	rcu_read_unlock();
+
+	return hctx;
+}
+
 static inline enum hctx_type blk_mq_get_hctx_type(blk_opf_t opf)
 {
 	enum hctx_type type = HCTX_TYPE_DEFAULT;
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 0795f29dd65d..484baf91fd91 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -1001,7 +1001,7 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
 
 #define queue_for_each_hw_ctx(q, hctx, i)				\
 	for ((i) = 0; (i) < (q)->nr_hw_queues &&			\
-	     ({ hctx = (q)->queue_hw_ctx[i]; 1; }); (i)++)
+	     ({ hctx = queue_hctx((q), i); 1; }); (i)++)
 
 #define hctx_for_each_ctx(hctx, ctx, i)					\
 	for ((i) = 0; (i) < (hctx)->nr_ctx &&				\
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 56328080ca09..f50f2d5eeb55 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -493,7 +493,7 @@ struct request_queue {
 
 	/* hw dispatch queues */
 	unsigned int		nr_hw_queues;
-	struct blk_mq_hw_ctx	**queue_hw_ctx;
+	struct blk_mq_hw_ctx __rcu	**queue_hw_ctx;
 
 	struct percpu_ref	q_usage_counter;
 	struct lock_class_key	io_lock_cls_key;
-- 
2.39.5 (Apple Git-154)


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

* Re: [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray
  2025-11-27  1:39 [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Fengnan Chang
  2025-11-27  1:39 ` [PATCH v2 1/2] " Fengnan Chang
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
@ 2025-11-27  2:47 ` Jens Axboe
  2025-11-27  2:55   ` fengnan chang
  2025-11-27  2:49 ` Jens Axboe
  3 siblings, 1 reply; 13+ messages in thread
From: Jens Axboe @ 2025-11-27  2:47 UTC (permalink / raw)
  To: Fengnan Chang, linux-block, ming.lei, hare, hch, yukuai3; +Cc: Fengnan Chang

On 11/26/25 6:39 PM, Fengnan Chang wrote:
> From: Fengnan Chang <changfengnan@bytedance.com>
> 
> After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
> an xarray instead of array to store hctx, but in poll mode, each time
> in blk_mq_poll, we need use xa_load to find corresponding hctx, this
> introduce some costs. In my test, xa_load may cost 3.8% cpu.
> 
> After revert previous change, eliminates the overhead of xa_load and can
> result in a 3% performance improvement.
> 
> potentital use-after-free on q->queue_hw_ctx can be fixed by use rcu to
> avoid, same as Yu Kuai did in [1].
> 
> [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/

What changed in v2? Neither this cover letter nor the patches have any
mention of that.

-- 
Jens Axboe


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

* Re: [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray
  2025-11-27  1:39 [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Fengnan Chang
                   ` (2 preceding siblings ...)
  2025-11-27  2:47 ` [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Jens Axboe
@ 2025-11-27  2:49 ` Jens Axboe
  2025-11-27  3:00   ` fengnan chang
  3 siblings, 1 reply; 13+ messages in thread
From: Jens Axboe @ 2025-11-27  2:49 UTC (permalink / raw)
  To: Fengnan Chang, linux-block, ming.lei, hare, hch; +Cc: Fengnan Chang, Yu Kuai

On 11/26/25 6:39 PM, Fengnan Chang wrote:
> From: Fengnan Chang <changfengnan@bytedance.com>
> 
> After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
> an xarray instead of array to store hctx, but in poll mode, each time
> in blk_mq_poll, we need use xa_load to find corresponding hctx, this
> introduce some costs. In my test, xa_load may cost 3.8% cpu.
> 
> After revert previous change, eliminates the overhead of xa_load and can
> result in a 3% performance improvement.
> 
> potentital use-after-free on q->queue_hw_ctx can be fixed by use rcu to
> avoid, same as Yu Kuai did in [1].
> 
> [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/
> 
> Fengnan Chang (2):
>   blk-mq: use array manage hctx map instead of xarray
>   blk-mq: fix potential uaf for 'queue_hw_ctx'
> 
>  block/blk-mq-tag.c     |  2 +-
>  block/blk-mq.c         | 63 ++++++++++++++++++++++++++++--------------
>  block/blk-mq.h         | 13 ++++++++-
>  include/linux/blk-mq.h |  3 +-
>  include/linux/blkdev.h |  2 +-
>  5 files changed, 58 insertions(+), 25 deletions(-)
> 
> 
> base-commit: 4941a17751c99e17422be743c02c923ad706f888

Adding correct Yu address, was also wrong for v1 and somehow not
corrected?

-- 
Jens Axboe


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

* Re: [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray
  2025-11-27  2:47 ` [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Jens Axboe
@ 2025-11-27  2:55   ` fengnan chang
  0 siblings, 0 replies; 13+ messages in thread
From: fengnan chang @ 2025-11-27  2:55 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, ming.lei, hare, hch, Fengnan Chang

On Thu, Nov 27, 2025 at 10:47 AM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 11/26/25 6:39 PM, Fengnan Chang wrote:
> > From: Fengnan Chang <changfengnan@bytedance.com>
> >
> > After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
> > an xarray instead of array to store hctx, but in poll mode, each time
> > in blk_mq_poll, we need use xa_load to find corresponding hctx, this
> > introduce some costs. In my test, xa_load may cost 3.8% cpu.
> >
> > After revert previous change, eliminates the overhead of xa_load and can
> > result in a 3% performance improvement.
> >
> > potentital use-after-free on q->queue_hw_ctx can be fixed by use rcu to
> > avoid, same as Yu Kuai did in [1].
> >
> > [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/
>
> What changed in v2? Neither this cover letter nor the patches have any
> mention of that.
Sorry for miss change description. Two change in V2:
1. modify synchronize_rcu() to synchronize_rcu_expedited()
2. use rcu_dereference(q->queue_hw_ctx)[id]  in queue_hctx to better read.

>
> --
> Jens Axboe
>

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

* Re: [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray
  2025-11-27  2:49 ` Jens Axboe
@ 2025-11-27  3:00   ` fengnan chang
  0 siblings, 0 replies; 13+ messages in thread
From: fengnan chang @ 2025-11-27  3:00 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, ming.lei, hare, hch, Fengnan Chang, Yu Kuai

On Thu, Nov 27, 2025 at 10:49 AM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 11/26/25 6:39 PM, Fengnan Chang wrote:
> > From: Fengnan Chang <changfengnan@bytedance.com>
> >
> > After commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray"), we use
> > an xarray instead of array to store hctx, but in poll mode, each time
> > in blk_mq_poll, we need use xa_load to find corresponding hctx, this
> > introduce some costs. In my test, xa_load may cost 3.8% cpu.
> >
> > After revert previous change, eliminates the overhead of xa_load and can
> > result in a 3% performance improvement.
> >
> > potentital use-after-free on q->queue_hw_ctx can be fixed by use rcu to
> > avoid, same as Yu Kuai did in [1].
> >
> > [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/
> >
> > Fengnan Chang (2):
> >   blk-mq: use array manage hctx map instead of xarray
> >   blk-mq: fix potential uaf for 'queue_hw_ctx'
> >
> >  block/blk-mq-tag.c     |  2 +-
> >  block/blk-mq.c         | 63 ++++++++++++++++++++++++++++--------------
> >  block/blk-mq.h         | 13 ++++++++-
> >  include/linux/blk-mq.h |  3 +-
> >  include/linux/blkdev.h |  2 +-
> >  5 files changed, 58 insertions(+), 25 deletions(-)
> >
> >
> > base-commit: 4941a17751c99e17422be743c02c923ad706f888
>
> Adding correct Yu address, was also wrong for v1 and somehow not
> corrected?
I didn't notice this, the error message was blocked in the spam folder.

>
> --
> Jens Axboe
>

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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
@ 2025-11-27  3:33   ` Ming Lei
  2025-11-27  3:38     ` Ming Lei
  2025-11-27 18:46   ` kernel test robot
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-11-27  3:33 UTC (permalink / raw)
  To: Fengnan Chang; +Cc: axboe, linux-block, hare, hch, yukuai3, Fengnan Chang

On Thu, Nov 27, 2025 at 09:39:08AM +0800, Fengnan Chang wrote:
> From: Fengnan Chang <changfengnan@bytedance.com>
> 
> This is just apply Kuai's patch in [1] with mirror changes.
> 
> blk_mq_realloc_hw_ctxs() will free the 'queue_hw_ctx'(e.g. undate
> submit_queues through configfs for null_blk), while it might still be
> used from other context(e.g. switch elevator to none):
> 
> t1					t2
> elevator_switch
>  blk_mq_unquiesce_queue
>   blk_mq_run_hw_queues
>    queue_for_each_hw_ctx
>     // assembly code for hctx = (q)->queue_hw_ctx[i]
>     mov    0x48(%rbp),%rdx -> read old queue_hw_ctx
> 
> 					__blk_mq_update_nr_hw_queues
> 					 blk_mq_realloc_hw_ctxs
> 					  hctxs = q->queue_hw_ctx
> 					  q->queue_hw_ctx = new_hctxs
> 					  kfree(hctxs)
>     movslq %ebx,%rax
>     mov    (%rdx,%rax,8),%rdi ->uaf
> 
> This problem was found by code review, and I comfirmed that the concurrent
> scenario do exist(specifically 'q->queue_hw_ctx' can be changed during
> blk_mq_run_hw_queues()), however, the uaf problem hasn't been repoduced yet
> without hacking the kernel.
> 
> Sicne the queue is freezed in __blk_mq_update_nr_hw_queues(), fix the
> problem by protecting 'queue_hw_ctx' through rcu where it can be accessed
> without grabbing 'q_usage_counter'.
> 
> [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/
> 
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
> Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
> ---
>  block/blk-mq.c         |  7 ++++++-
>  block/blk-mq.h         | 11 +++++++++++
>  include/linux/blk-mq.h |  2 +-
>  include/linux/blkdev.h |  2 +-
>  4 files changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index eed12fab3484..0b8b72194003 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -4524,7 +4524,12 @@ static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
>  		if (hctxs)
>  			memcpy(new_hctxs, hctxs, q->nr_hw_queues *
>  			       sizeof(*hctxs));
> -		q->queue_hw_ctx = new_hctxs;
> +		rcu_assign_pointer(q->queue_hw_ctx, new_hctxs);
> +		/*
> +		 * Make sure reading the old queue_hw_ctx from other
> +		 * context concurrently won't trigger uaf.
> +		 */
> +		synchronize_rcu_expedited();
>  		kfree(hctxs);
>  		hctxs = new_hctxs;
>  	}
> diff --git a/block/blk-mq.h b/block/blk-mq.h
> index 80a3f0c2bce7..52852fab78f0 100644
> --- a/block/blk-mq.h
> +++ b/block/blk-mq.h
> @@ -87,6 +87,17 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *
>  	return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]];
>  }
>  
> +static inline struct blk_mq_hw_ctx *queue_hctx(struct request_queue *q, int id)
> +{
> +	struct blk_mq_hw_ctx *hctx;
> +
> +	rcu_read_lock();
> +	hctx = rcu_dereference(q->queue_hw_ctx)[id];
> +	rcu_read_unlock();
> +
> +	return hctx;
> +}


If `hctx` is retrieved from old table, uaf will be triggered on
`hctx` dereference after returning from queue_hctx().

So rcu read lock should be held anywhere for `hctx` deference.



Thanks, 
Ming


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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  3:33   ` Ming Lei
@ 2025-11-27  3:38     ` Ming Lei
  0 siblings, 0 replies; 13+ messages in thread
From: Ming Lei @ 2025-11-27  3:38 UTC (permalink / raw)
  To: Fengnan Chang; +Cc: axboe, linux-block, hare, hch, yukuai3, Fengnan Chang

On Thu, Nov 27, 2025 at 11:33:22AM +0800, Ming Lei wrote:
> On Thu, Nov 27, 2025 at 09:39:08AM +0800, Fengnan Chang wrote:
> > From: Fengnan Chang <changfengnan@bytedance.com>
> > 
> > This is just apply Kuai's patch in [1] with mirror changes.
> > 
> > blk_mq_realloc_hw_ctxs() will free the 'queue_hw_ctx'(e.g. undate
> > submit_queues through configfs for null_blk), while it might still be
> > used from other context(e.g. switch elevator to none):
> > 
> > t1					t2
> > elevator_switch
> >  blk_mq_unquiesce_queue
> >   blk_mq_run_hw_queues
> >    queue_for_each_hw_ctx
> >     // assembly code for hctx = (q)->queue_hw_ctx[i]
> >     mov    0x48(%rbp),%rdx -> read old queue_hw_ctx
> > 
> > 					__blk_mq_update_nr_hw_queues
> > 					 blk_mq_realloc_hw_ctxs
> > 					  hctxs = q->queue_hw_ctx
> > 					  q->queue_hw_ctx = new_hctxs
> > 					  kfree(hctxs)
> >     movslq %ebx,%rax
> >     mov    (%rdx,%rax,8),%rdi ->uaf
> > 
> > This problem was found by code review, and I comfirmed that the concurrent
> > scenario do exist(specifically 'q->queue_hw_ctx' can be changed during
> > blk_mq_run_hw_queues()), however, the uaf problem hasn't been repoduced yet
> > without hacking the kernel.
> > 
> > Sicne the queue is freezed in __blk_mq_update_nr_hw_queues(), fix the
> > problem by protecting 'queue_hw_ctx' through rcu where it can be accessed
> > without grabbing 'q_usage_counter'.
> > 
> > [1] https://lore.kernel.org/all/20220225072053.2472431-1-yukuai3@huawei.com/
> > 
> > Signed-off-by: Yu Kuai <yukuai3@huawei.com>
> > Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
> > ---
> >  block/blk-mq.c         |  7 ++++++-
> >  block/blk-mq.h         | 11 +++++++++++
> >  include/linux/blk-mq.h |  2 +-
> >  include/linux/blkdev.h |  2 +-
> >  4 files changed, 19 insertions(+), 3 deletions(-)
> > 
> > diff --git a/block/blk-mq.c b/block/blk-mq.c
> > index eed12fab3484..0b8b72194003 100644
> > --- a/block/blk-mq.c
> > +++ b/block/blk-mq.c
> > @@ -4524,7 +4524,12 @@ static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
> >  		if (hctxs)
> >  			memcpy(new_hctxs, hctxs, q->nr_hw_queues *
> >  			       sizeof(*hctxs));
> > -		q->queue_hw_ctx = new_hctxs;
> > +		rcu_assign_pointer(q->queue_hw_ctx, new_hctxs);
> > +		/*
> > +		 * Make sure reading the old queue_hw_ctx from other
> > +		 * context concurrently won't trigger uaf.
> > +		 */
> > +		synchronize_rcu_expedited();
> >  		kfree(hctxs);
> >  		hctxs = new_hctxs;
> >  	}
> > diff --git a/block/blk-mq.h b/block/blk-mq.h
> > index 80a3f0c2bce7..52852fab78f0 100644
> > --- a/block/blk-mq.h
> > +++ b/block/blk-mq.h
> > @@ -87,6 +87,17 @@ static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *
> >  	return q->queue_hw_ctx[q->tag_set->map[type].mq_map[cpu]];
> >  }
> >  
> > +static inline struct blk_mq_hw_ctx *queue_hctx(struct request_queue *q, int id)
> > +{
> > +	struct blk_mq_hw_ctx *hctx;
> > +
> > +	rcu_read_lock();
> > +	hctx = rcu_dereference(q->queue_hw_ctx)[id];
> > +	rcu_read_unlock();
> > +
> > +	return hctx;
> > +}
> 
> 
> If `hctx` is retrieved from old table, uaf will be triggered on
> `hctx` dereference after returning from queue_hctx().
> 
> So rcu read lock should be held anywhere for `hctx` deference.

oops, the rcu read lock only protects `q->queue_hw_ctx`, so this
way is fine, sorry for the noise!


Thanks. 
Ming


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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
  2025-11-27  3:33   ` Ming Lei
@ 2025-11-27 18:46   ` kernel test robot
  2025-11-27 20:30   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-11-27 18:46 UTC (permalink / raw)
  To: Fengnan Chang, axboe, linux-block, ming.lei, hare, hch, yukuai3
  Cc: llvm, oe-kbuild-all, Fengnan Chang

Hi Fengnan,

kernel test robot noticed the following build errors:

[auto build test ERROR on 4941a17751c99e17422be743c02c923ad706f888]

url:    https://github.com/intel-lab-lkp/linux/commits/Fengnan-Chang/blk-mq-use-array-manage-hctx-map-instead-of-xarray/20251127-094243
base:   4941a17751c99e17422be743c02c923ad706f888
patch link:    https://lore.kernel.org/r/20251127013908.66118-3-fengnanchang%40gmail.com
patch subject: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20251128/202511280210.BjxdaKJc-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251128/202511280210.BjxdaKJc-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511280210.BjxdaKJc-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/block/rnbd/rnbd-clt.c:1324:2: error: call to undeclared function 'queue_hctx'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    1324 |         queue_for_each_hw_ctx(dev->queue, hctx, i) {
         |         ^
   include/linux/blk-mq.h:1004:17: note: expanded from macro 'queue_for_each_hw_ctx'
    1004 |              ({ hctx = queue_hctx((q), i); 1; }); (i)++)
         |                        ^
>> drivers/block/rnbd/rnbd-clt.c:1324:2: error: incompatible integer to pointer conversion assigning to 'struct blk_mq_hw_ctx *' from 'int' [-Wint-conversion]
    1324 |         queue_for_each_hw_ctx(dev->queue, hctx, i) {
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/blk-mq.h:1004:15: note: expanded from macro 'queue_for_each_hw_ctx'
    1004 |              ({ hctx = queue_hctx((q), i); 1; }); (i)++)
         |                      ^ ~~~~~~~~~~~~~~~~~~
   2 errors generated.


vim +/queue_hctx +1324 drivers/block/rnbd/rnbd-clt.c

f7a7a5c228d45e Jack Wang 2020-05-11  1317  
f7a7a5c228d45e Jack Wang 2020-05-11  1318  static void rnbd_init_mq_hw_queues(struct rnbd_clt_dev *dev)
f7a7a5c228d45e Jack Wang 2020-05-11  1319  {
4f481208749a22 Ming Lei  2022-03-08  1320  	unsigned long i;
f7a7a5c228d45e Jack Wang 2020-05-11  1321  	struct blk_mq_hw_ctx *hctx;
f7a7a5c228d45e Jack Wang 2020-05-11  1322  	struct rnbd_queue *q;
f7a7a5c228d45e Jack Wang 2020-05-11  1323  
f7a7a5c228d45e Jack Wang 2020-05-11 @1324  	queue_for_each_hw_ctx(dev->queue, hctx, i) {
f7a7a5c228d45e Jack Wang 2020-05-11  1325  		q = &dev->hw_queues[i];
f7a7a5c228d45e Jack Wang 2020-05-11  1326  		rnbd_init_hw_queue(dev, q, hctx);
f7a7a5c228d45e Jack Wang 2020-05-11  1327  		hctx->driver_data = q;
f7a7a5c228d45e Jack Wang 2020-05-11  1328  	}
f7a7a5c228d45e Jack Wang 2020-05-11  1329  }
f7a7a5c228d45e Jack Wang 2020-05-11  1330  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
  2025-11-27  3:33   ` Ming Lei
  2025-11-27 18:46   ` kernel test robot
@ 2025-11-27 20:30   ` kernel test robot
  2025-11-27 20:41   ` kernel test robot
  2025-11-27 23:32   ` kernel test robot
  4 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-11-27 20:30 UTC (permalink / raw)
  To: Fengnan Chang, axboe, linux-block, ming.lei, hare, hch, yukuai3
  Cc: oe-kbuild-all, Fengnan Chang

Hi Fengnan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 4941a17751c99e17422be743c02c923ad706f888]

url:    https://github.com/intel-lab-lkp/linux/commits/Fengnan-Chang/blk-mq-use-array-manage-hctx-map-instead-of-xarray/20251127-094243
base:   4941a17751c99e17422be743c02c923ad706f888
patch link:    https://lore.kernel.org/r/20251127013908.66118-3-fengnanchang%40gmail.com
patch subject: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
config: arm64-randconfig-r131-20251128 (https://download.01.org/0day-ci/archive/20251128/202511280340.4LxTSm2A-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251128/202511280340.4LxTSm2A-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511280340.4LxTSm2A-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   block/blk-mq-sysfs.c: note: in included file:
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
--
   block/blk-mq-sched.c: note: in included file:
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
--
   block/blk-mq-tag.c: note: in included file:
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
--
   block/blk-mq-debugfs.c: note: in included file:
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
--
   block/kyber-iosched.c: note: in included file (through block/elevator.h):
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
--
   block/blk-mq.c:726:19: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct blk_mq_hw_ctx *hctx @@     got struct blk_mq_hw_ctx [noderef] __rcu * @@
   block/blk-mq.c:726:19: sparse:     expected struct blk_mq_hw_ctx *hctx
   block/blk-mq.c:726:19: sparse:     got struct blk_mq_hw_ctx [noderef] __rcu *
   block/blk-mq.c:4514:41: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct blk_mq_hw_ctx **hctxs @@     got struct blk_mq_hw_ctx [noderef] __rcu **queue_hw_ctx @@
   block/blk-mq.c:4514:41: sparse:     expected struct blk_mq_hw_ctx **hctxs
   block/blk-mq.c:4514:41: sparse:     got struct blk_mq_hw_ctx [noderef] __rcu **queue_hw_ctx
   block/blk-mq.c:4527:17: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.c:4527:17: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.c:4527:17: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.c:5192:48: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct blk_mq_hw_ctx *hctx @@     got struct blk_mq_hw_ctx [noderef] __rcu * @@
   block/blk-mq.c:5192:48: sparse:     expected struct blk_mq_hw_ctx *hctx
   block/blk-mq.c:5192:48: sparse:     got struct blk_mq_hw_ctx [noderef] __rcu *
   block/blk-mq.c: note: in included file:
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **
>> block/blk-mq.h:95:16: sparse: sparse: incompatible types in comparison expression (different address spaces):
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu *[noderef] __rcu *
   block/blk-mq.h:95:16: sparse:    struct blk_mq_hw_ctx [noderef] __rcu **

vim +95 block/blk-mq.h

    89	
    90	static inline struct blk_mq_hw_ctx *queue_hctx(struct request_queue *q, int id)
    91	{
    92		struct blk_mq_hw_ctx *hctx;
    93	
    94		rcu_read_lock();
  > 95		hctx = rcu_dereference(q->queue_hw_ctx)[id];
    96		rcu_read_unlock();
    97	
    98		return hctx;
    99	}
   100	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
                     ` (2 preceding siblings ...)
  2025-11-27 20:30   ` kernel test robot
@ 2025-11-27 20:41   ` kernel test robot
  2025-11-27 23:32   ` kernel test robot
  4 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-11-27 20:41 UTC (permalink / raw)
  To: Fengnan Chang, axboe, linux-block, ming.lei, hare, hch, yukuai3
  Cc: oe-kbuild-all, Fengnan Chang

Hi Fengnan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 4941a17751c99e17422be743c02c923ad706f888]

url:    https://github.com/intel-lab-lkp/linux/commits/Fengnan-Chang/blk-mq-use-array-manage-hctx-map-instead-of-xarray/20251127-094243
base:   4941a17751c99e17422be743c02c923ad706f888
patch link:    https://lore.kernel.org/r/20251127013908.66118-3-fengnanchang%40gmail.com
patch subject: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
config: arm-randconfig-002-20251128 (https://download.01.org/0day-ci/archive/20251128/202511280407.DzqlGFFg-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251128/202511280407.DzqlGFFg-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511280407.DzqlGFFg-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/block/rnbd/rnbd-clt.h:16,
                    from drivers/block/rnbd/rnbd-clt.c:19:
   drivers/block/rnbd/rnbd-clt.c: In function 'rnbd_init_mq_hw_queues':
   include/linux/blk-mq.h:1004:17: error: implicit declaration of function 'queue_hctx'; did you mean 'queue_work'? [-Werror=implicit-function-declaration]
          ({ hctx = queue_hctx((q), i); 1; }); (i)++)
                    ^~~~~~~~~~
   drivers/block/rnbd/rnbd-clt.c:1324:2: note: in expansion of macro 'queue_for_each_hw_ctx'
     queue_for_each_hw_ctx(dev->queue, hctx, i) {
     ^~~~~~~~~~~~~~~~~~~~~
>> include/linux/blk-mq.h:1004:15: warning: assignment to 'struct blk_mq_hw_ctx *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
          ({ hctx = queue_hctx((q), i); 1; }); (i)++)
                  ^
   drivers/block/rnbd/rnbd-clt.c:1324:2: note: in expansion of macro 'queue_for_each_hw_ctx'
     queue_for_each_hw_ctx(dev->queue, hctx, i) {
     ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   In file included from rnbd-clt.h:16,
                    from rnbd-clt.c:19:
   rnbd-clt.c: In function 'rnbd_init_mq_hw_queues':
   include/linux/blk-mq.h:1004:17: error: implicit declaration of function 'queue_hctx'; did you mean 'queue_work'? [-Werror=implicit-function-declaration]
          ({ hctx = queue_hctx((q), i); 1; }); (i)++)
                    ^~~~~~~~~~
   rnbd-clt.c:1324:2: note: in expansion of macro 'queue_for_each_hw_ctx'
     queue_for_each_hw_ctx(dev->queue, hctx, i) {
     ^~~~~~~~~~~~~~~~~~~~~
>> include/linux/blk-mq.h:1004:15: warning: assignment to 'struct blk_mq_hw_ctx *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
          ({ hctx = queue_hctx((q), i); 1; }); (i)++)
                  ^
   rnbd-clt.c:1324:2: note: in expansion of macro 'queue_for_each_hw_ctx'
     queue_for_each_hw_ctx(dev->queue, hctx, i) {
     ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +1004 include/linux/blk-mq.h

  1001	
  1002	#define queue_for_each_hw_ctx(q, hctx, i)				\
  1003		for ((i) = 0; (i) < (q)->nr_hw_queues &&			\
> 1004		     ({ hctx = queue_hctx((q), i); 1; }); (i)++)
  1005	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
  2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
                     ` (3 preceding siblings ...)
  2025-11-27 20:41   ` kernel test robot
@ 2025-11-27 23:32   ` kernel test robot
  4 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-11-27 23:32 UTC (permalink / raw)
  To: Fengnan Chang, axboe, linux-block, ming.lei, hare, hch, yukuai3
  Cc: oe-kbuild-all, Fengnan Chang

Hi Fengnan,

kernel test robot noticed the following build errors:

[auto build test ERROR on 4941a17751c99e17422be743c02c923ad706f888]

url:    https://github.com/intel-lab-lkp/linux/commits/Fengnan-Chang/blk-mq-use-array-manage-hctx-map-instead-of-xarray/20251127-094243
base:   4941a17751c99e17422be743c02c923ad706f888
patch link:    https://lore.kernel.org/r/20251127013908.66118-3-fengnanchang%40gmail.com
patch subject: [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx'
config: um-allyesconfig (https://download.01.org/0day-ci/archive/20251128/202511280714.MCsRsCmR-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251128/202511280714.MCsRsCmR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511280714.MCsRsCmR-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/block/rnbd/rnbd-clt.h:16,
                    from drivers/block/rnbd/rnbd-clt.c:19:
   drivers/block/rnbd/rnbd-clt.c: In function 'rnbd_init_mq_hw_queues':
>> include/linux/blk-mq.h:1004:24: error: implicit declaration of function 'queue_hctx' [-Wimplicit-function-declaration]
    1004 |              ({ hctx = queue_hctx((q), i); 1; }); (i)++)
         |                        ^~~~~~~~~~
   drivers/block/rnbd/rnbd-clt.c:1324:9: note: in expansion of macro 'queue_for_each_hw_ctx'
    1324 |         queue_for_each_hw_ctx(dev->queue, hctx, i) {
         |         ^~~~~~~~~~~~~~~~~~~~~
>> include/linux/blk-mq.h:1004:22: error: assignment to 'struct blk_mq_hw_ctx *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
    1004 |              ({ hctx = queue_hctx((q), i); 1; }); (i)++)
         |                      ^
   drivers/block/rnbd/rnbd-clt.c:1324:9: note: in expansion of macro 'queue_for_each_hw_ctx'
    1324 |         queue_for_each_hw_ctx(dev->queue, hctx, i) {
         |         ^~~~~~~~~~~~~~~~~~~~~


vim +/queue_hctx +1004 include/linux/blk-mq.h

  1001	
  1002	#define queue_for_each_hw_ctx(q, hctx, i)				\
  1003		for ((i) = 0; (i) < (q)->nr_hw_queues &&			\
> 1004		     ({ hctx = queue_hctx((q), i); 1; }); (i)++)
  1005	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2025-11-27 23:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-27  1:39 [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Fengnan Chang
2025-11-27  1:39 ` [PATCH v2 1/2] " Fengnan Chang
2025-11-27  1:39 ` [PATCH v2 2/2] blk-mq: fix potential uaf for 'queue_hw_ctx' Fengnan Chang
2025-11-27  3:33   ` Ming Lei
2025-11-27  3:38     ` Ming Lei
2025-11-27 18:46   ` kernel test robot
2025-11-27 20:30   ` kernel test robot
2025-11-27 20:41   ` kernel test robot
2025-11-27 23:32   ` kernel test robot
2025-11-27  2:47 ` [PATCH v2 0/2] blk-mq: use array manage hctx map instead of xarray Jens Axboe
2025-11-27  2:55   ` fengnan chang
2025-11-27  2:49 ` Jens Axboe
2025-11-27  3:00   ` fengnan chang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).