All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hyokyung Kim <pulpannie@gmail.com>
To: stable@vger.kernel.org
Cc: Sasha Levin <sashal@kernel.org>,
	"Michael S . Tsirkin" <mst@redhat.com>,
	Jason Wang <jasowang@redhat.com>,
	Philo Lu <lulie@linux.alibaba.com>,
	Xuan Zhuo <xuanzhuo@linux.alibaba.com>,
	Joe Damato <jdamato@fastly.com>, Paolo Abeni <pabeni@redhat.com>,
	Hyokyung Kim <pulpannie@gmail.com>
Subject: [PATCH 6.1.y] virtio_net: Support dynamic rss indirection table size
Date: Fri, 10 Jul 2026 11:25:21 +0000	[thread overview]
Message-ID: <20260710112521.234909-1-pulpannie@gmail.com> (raw)
In-Reply-To: <CAGJdW3H0Bv31W5DNaHstXyYxMcVFUnOmzAJ9LAjZOANk1y67OQ@mail.gmail.com>

From: Philo Lu <lulie@linux.alibaba.com>

commit 86a48a00efdf61197b6658e52c6140463eb313dc upstream.

When reading/writing virtio_net_ctrl_rss, the indirection table size is
obtained from vi->rss_indir_table_size, initialized during virtnet_probe().
However, the indirection_table was statically sized as
VIRTIO_NET_RSS_MAX_TABLE_LEN=128, potentially causing issues when
vi->rss_indir_table_size exceeds this limit.

This patch implements dynamic allocation for the indirection table,
allocated alongside vi->rss after vi->rss_indir_table_size is initialized,
and freed in virtnet_remove().

In virtnet_commit_rss_command(), scatter-gather lists for RSS are
initialized differently based on hash_report presence, so indirection_table
is unused when !vi->has_rss. Therefore, allocation is unnecessary for
hash_report-only scenarios.

Fixes: c7114b1249fa ("drivers/net/virtio_net: Added basic RSS support.")
Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Acked-by: Joe Damato <jdamato@fastly.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
[ Hyokyung Kim: 6.1.y predates the refactor that moved the RSS config into
  struct virtnet_info, so struct virtio_net_ctrl_rss is still embedded in
  struct control_buf and reached through the heap-allocated vi->ctrl. Every
  adaptation below follows from that single difference:
  - the new allocation and all indirection_table accesses use vi->ctrl->rss
    in place of upstream's vi->rss;
  - because vi->ctrl is allocated in virtnet_alloc_queues() (via init_vqs())
    and freed in virtnet_free_queues(), the table is allocated and freed there
    too, not in virtnet_probe()/virtnet_remove(), so its lifetime tracks
    vi->ctrl across the probe error-unwind and freeze/restore paths;
  - since freeing the table now dereferences vi->ctrl, vi->ctrl is set to NULL
    after each kfree so a re-entered virtnet_free_queues() cannot dereference
    or free a stale pointer;
  - the table is allocated with kcalloc() so it is zero-filled when
    reallocated on the restore path (upstream never reallocates it). ]
Signed-off-by: Hyokyung Kim <pulpannie@gmail.com>
---
 drivers/net/virtio_net.c | 43 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index b62b769631..2fb00df795 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -179,15 +179,16 @@ struct receive_queue {
  * because table sizes may be differ according to the device configuration.
  */
 #define VIRTIO_NET_RSS_MAX_KEY_SIZE     40
-#define VIRTIO_NET_RSS_MAX_TABLE_LEN    128
 struct virtio_net_ctrl_rss {
 	u32 hash_types;
 	u16 indirection_table_mask;
 	u16 unclassified_queue;
-	u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN];
+	u16 hash_cfg_reserved; /* for HASH_CONFIG (see virtio_net_hash_config for details) */
 	u16 max_tx_vq;
 	u8 hash_key_length;
 	u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
+
+	u16 *indirection_table;
 };
 
 /* Control VQ buffers: protected by the rtnl lock */
@@ -2488,6 +2489,25 @@ static int virtnet_set_ringparam(struct net_device *dev,
 	return 0;
 }
 
+static int rss_indirection_table_alloc(struct virtio_net_ctrl_rss *rss, u16 indir_table_size)
+{
+	if (!indir_table_size) {
+		rss->indirection_table = NULL;
+		return 0;
+	}
+
+	rss->indirection_table = kcalloc(indir_table_size, sizeof(u16), GFP_KERNEL);
+	if (!rss->indirection_table)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void rss_indirection_table_free(struct virtio_net_ctrl_rss *rss)
+{
+	kfree(rss->indirection_table);
+}
+
 static bool virtnet_commit_rss_command(struct virtnet_info *vi)
 {
 	struct net_device *dev = vi->dev;
@@ -2497,11 +2517,15 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
 	/* prepare sgs */
 	sg_init_table(sgs, 4);
 
-	sg_buf_size = offsetof(struct virtio_net_ctrl_rss, indirection_table);
+	sg_buf_size = offsetof(struct virtio_net_ctrl_rss, hash_cfg_reserved);
 	sg_set_buf(&sgs[0], &vi->ctrl->rss, sg_buf_size);
 
-	sg_buf_size = sizeof(uint16_t) * (vi->ctrl->rss.indirection_table_mask + 1);
-	sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size);
+	if (vi->has_rss) {
+		sg_buf_size = sizeof(uint16_t) * vi->rss_indir_table_size;
+		sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size);
+	} else {
+		sg_set_buf(&sgs[1], &vi->ctrl->rss.hash_cfg_reserved, sizeof(uint16_t));
+	}
 
 	sg_buf_size = offsetof(struct virtio_net_ctrl_rss, key)
 			- offsetof(struct virtio_net_ctrl_rss, max_tx_vq);
@@ -3415,7 +3439,10 @@ static void virtnet_free_queues(struct virtnet_info *vi)
 
 	kfree(vi->rq);
 	kfree(vi->sq);
+	if (vi->ctrl)
+		rss_indirection_table_free(&vi->ctrl->rss);
 	kfree(vi->ctrl);
+	vi->ctrl = NULL;
 }
 
 static void _free_receive_bufs(struct virtnet_info *vi)
@@ -3610,6 +3637,9 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
 		vi->ctrl = kzalloc(sizeof(*vi->ctrl), GFP_KERNEL);
 		if (!vi->ctrl)
 			goto err_ctrl;
+		if ((vi->has_rss || vi->has_rss_hash_report) &&
+		    rss_indirection_table_alloc(&vi->ctrl->rss, vi->rss_indir_table_size))
+			goto err_sq;
 	} else {
 		vi->ctrl = NULL;
 	}
@@ -3642,7 +3672,10 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
 err_rq:
 	kfree(vi->sq);
 err_sq:
+	if (vi->ctrl)
+		rss_indirection_table_free(&vi->ctrl->rss);
 	kfree(vi->ctrl);
+	vi->ctrl = NULL;
 err_ctrl:
 	return -ENOMEM;
 }
-- 
2.53.0


  parent reply	other threads:[~2026-07-10 11:25 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-30  0:51 [LTS Backport Request] Fix RSS indirection table OOB write (6.1.y, 6.6.y) Annie Kim
2026-06-30 22:23 ` Sasha Levin
2026-07-03 10:50   ` [PATCH 6.6.y] virtio_net: clamp rss_indir_table_size to VIRTIO_NET_RSS_MAX_TABLE_LEN Hyokyung Kim
2026-07-04  2:05     ` Sasha Levin
2026-07-06  5:48       ` Annie Kim
2026-07-03 10:52   ` [PATCH 6.1.y] " Hyokyung Kim
2026-08-20 13:49     ` Greg KH
2026-08-21  4:33       ` Sasha Levin
2026-07-10 11:19 ` [PATCH 6.6.y] virtio_net: Support dynamic rss indirection table size Hyokyung Kim
2026-07-10 21:03   ` Sasha Levin
2026-07-10 11:25 ` Hyokyung Kim [this message]
2026-07-10 21:03   ` [PATCH 6.1.y] " Sasha Levin
2026-07-10 12:49 ` [PATCH 6.6.y] " Hyokyung Kim

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=20260710112521.234909-1-pulpannie@gmail.com \
    --to=pulpannie@gmail.com \
    --cc=jasowang@redhat.com \
    --cc=jdamato@fastly.com \
    --cc=lulie@linux.alibaba.com \
    --cc=mst@redhat.com \
    --cc=pabeni@redhat.com \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=xuanzhuo@linux.alibaba.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.