From nobody Tue Sep 29 05:34:23 2026 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (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 0585331F9A0 for ; Wed, 12 Aug 2026 05:22:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786512138; cv=none; b=Axlvu2vgOmi4hqNxACQptt7F1AuMo4tVwUtVpdaE7l8tfQuhBrvUd1ac6PaaGvJZK0RmehF5YTS3Er4yf74QRjNncY+Zh7qniHtD5lAmQTnZbNzDAoWCWUlTerBc2P5aH8Yja0S1Q59u0XUes6eaNuGT143BgYd4cOBMqLU62O8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786512138; c=relaxed/simple; bh=ibwpRO9tdzRnB9hwRdiCbyvha37TSoCPH2xljG79eqg=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=cvPz4h3Q7owRrUGMQ46JC49ZY7qnyNSBIDNEWFR9RSQWUW0fzF92LRnrRogbhYcKU51K7hFk+1vE0gOUszPc37DludvPnRKbqtByC/VdBDdcpQRJ6mg21AJiByLmfTl78ZSew6qsXNSGDqnADryCWjxLp65fOv9QIvu0qqm8mNM= 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=C6yiS7e4; arc=none smtp.client-ip=209.85.215.180 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="C6yiS7e4" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-cbb8b54fcf8so455772a12.0 for ; Tue, 11 Aug 2026 22:22:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786512136; x=1787116936; 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:content-type; bh=diIcC2mYMoxigl9uIM8y5rRAYyfw1dzo8pm6pfntNRk=; b=C6yiS7e4PB8oRktQoMCAxAAJabO2rmAayk6dsKGP62eRfqZYQqqKplfM3kRVHHXf+m GYkN8pCMwWYBaqt5q5O5xOWa5pEpfD5CE9IMSMxfhGUjqXzVrqEbOZA8mUghJcML9SoH HZO2oDmPdavfvqg2u1fLenRlFoYpASYx90Ue4lDe35Q6gsim2j3NXxk+f3aohlrz1eGd TBqClMezJOgNJ2SSqOxnY7FYTon1t3n6/VJp/cO7ExNuVKWgxVBCKRcxNNf3H41bxDJz uuWpEa0QxQFb34qQ44AmqZM+Ann2IwNxJvEdoeZHxDf5tUkTGsxWqKpEjreSOGiIeJ/d 67sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786512136; x=1787116936; 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:content-type; bh=diIcC2mYMoxigl9uIM8y5rRAYyfw1dzo8pm6pfntNRk=; b=so/JlmORVHLzhPzRK6MW/3ZO/FOVM6Rp/q5UyynAHC83N3Aj1wyeRq0USslX6m7MAf zMCGrSEaPJUEQeG1Tnzo1TnVXkDP60N6mjTDZbrLe1kIb3DbTH3t6+Rz8A6zMoo2jeoV EEk2HlrGGBOF/MmYTuKwpU+1tkWIchPyLikIKgxj4cs14PusoUBHeCp5ufwRd2y37yIA cblVFBVOLaCf1+Qjg9IE6GDX/Ao1IplaCPkN0dyiZKSKT2xw3maeSCuLvabfN60WrEHW /xUfA2AGPZEhCmfgGZjkeAsHNqg41COBQr5OTUI67bzYxnrp4/EW9XELLN/cr91FzpOz QqfA== X-Forwarded-Encrypted: i=1; AHgh+Rp6NDF6Stkp2TGmQ8GWS7Lzx4pkDS2lTlAK86gz/L5YIQkII9OApx2fKdTpnUtdO0iCIQVQiP4Jlsz8VP0=@vger.kernel.org X-Gm-Message-State: AOJu0YweXmBMdb0KdtIcJ4khuxkw1qiUaPl01RgQPMT81+Nz8TaLVxlG ZgfhiOwUiB+ljNO5cFM5v6bsNNaptLQJX6kB9fYlDu+hg7jOWaDu9zWL X-Gm-Gg: AR+sD13u47u74HwhMSc3IncomemeEM0C554d+E3tgzARkQE5v9FHTYtXtiILo7GEZj8 rH5feamfi/IXf9ivcSohEVlQcQO1DfDWh8wAfvW3kZN7NmMLi7NkBGl9+opCkeN4pXhyx2artTx kGpAJT8USAipbSmaN/ZHVYxJQr9/uBwDmP5qKJYwHwkPez+WXhIwfywWedaMD9jK3MYu1IC7K/8 whCKEU0gIsWGElCi3ZnuZ58hQ+pIfxTRqTDSpl1i3VGFBhV1eJZg4liVZF5BzhQRpfxi6teW132 jOZohP5GQ2cb+0M8CcbKVnw6j43KKd8h8ZpQOVFyqyCHQxoWBYG6Rk6Wc0XwilW+7S/aPCIZAQf qx89e/uP8RUR2xy7hvlwOJ0VUzfqCKkGVlqZT1nIYiogX71T1UvVOsPi7fSApP8odWYrH03IU4Z D9iyLneEk5ZwMXWqcv+Msf9Dgwh6BWCTwp49MFrlSySgIAwec9Z405C7jbWjH871m7+9d7YM17j fJ4JqKjXO8i X-Received: by 2002:a05:6a21:1509:b0:3c3:7cfe:b32a with SMTP id adf61e73a8af0-3cc3f735f3fmr2725770637.27.1786512135917; Tue, 11 Aug 2026 22:22:15 -0700 (PDT) Received: from Vinkys-MacBook-Air-39.local ([45.135.228.72]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-141244511afsm6026783c88.3.2026.08.11.22.22.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Aug 2026 22:22:15 -0700 (PDT) From: Qi Zhang To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com Cc: horms@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, nicoyip.dev@gmail.com, Qi Zhang Subject: [PATCH net v2] net: pktgen: use a consistent flow count Date: Wed, 12 Aug 2026 13:21:30 +0800 Message-ID: <20260812052130.32823-1-marsy12010123@gmail.com> X-Mailer: git-send-email 2.54.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" pktgen_if_write() can update cflows while the packet generator thread is inside mod_cur_headers(). The latter first tests cflows, but f_pick() then reloads it when selecting a random flow. This allows the following interleaving: CPU 0 (kpktgend) CPU 1 (proc write) if (pkt_dev->cflows) // 10 pkt_dev->cflows =3D 0 get_random_u32_below(pkt_dev->cflows) get_random_u32_below(0) returns a full-width random value. Using that value as an index into the fixed-size flows array causes an out-of-bounds access. The kernel reported: BUG: unable to handle page fault for address: ffffc8fe2d2674bc #PF: supervisor read access in kernel mode Oops: Oops: 0000 [#1] SMP KASAN NOPTI CPU: 0 UID: 0 PID: 65 Comm: kpktgend_0 RIP: 0010:mod_cur_headers+0x16f8/0x2840 Call Trace: pktgen_thread_worker+0x305a/0x6bc0 kthread+0x2c6/0x3b0 ret_from_fork+0x36e/0x5a0 ret_from_fork_asm+0x1a/0x30 Read cflows once at the start of mod_cur_headers(), pass the snapshot to f_pick(), and use it for later flow-state decisions in the same packet. Publish proc updates with WRITE_ONCE(). Flow selection then always uses a nonzero count bounded by MAX_CFLOWS, while a concurrent update takes effect on a later packet. Fixes: 007a531b0a0c ("[PKTGEN]: Introduce sequential flows") Cc: stable@vger.kernel.org Signed-off-by: Chengfeng Ye Signed-off-by: Qi Zhang Reviewed-by: Simon Horman --- v2: - Use the written value when reporting the new flow count. - Add READ_ONCE() to the remaining lockless cflows reads, including pktgen_if_show(), as suggested by Paolo Abeni. v1: https://lore.kernel.org/r/20260802152309.821584-1-marsy12010123@gmail.c= om net/core/pktgen.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index ee64f3012..e14bb9a48 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -566,6 +566,7 @@ static const struct proc_ops pktgen_proc_ops =3D { static int pktgen_if_show(struct seq_file *seq, void *v) { const struct pktgen_dev *pkt_dev =3D seq->private; + unsigned int cflows =3D READ_ONCE(pkt_dev->cflows); ktime_t stopped; unsigned int i; u64 idle; @@ -590,7 +591,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v) pkt_dev->nfrags, (unsigned long long) pkt_dev->delay, pkt_dev->clone_skb, pkt_dev->odevname); =20 - seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, + seq_printf(seq, " flows: %u flowlen: %u\n", cflows, pkt_dev->lflow); =20 seq_printf(seq, @@ -675,7 +676,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v) =20 for (i =3D 0; i < NR_PKT_FLAGS; i++) { if (i =3D=3D FLOW_SEQ_SHIFT) - if (!pkt_dev->cflows) + if (!cflows) continue; =20 if (pkt_dev->flags & (1 << i)) { @@ -1632,8 +1633,8 @@ static ssize_t pktgen_if_write(struct file *file, if (value > MAX_CFLOWS) value =3D MAX_CFLOWS; =20 - pkt_dev->cflows =3D value; - sprintf(pg_result, "OK: flows=3D%u", pkt_dev->cflows); + WRITE_ONCE(pkt_dev->cflows, value); + sprintf(pg_result, "OK: flows=3D%u", (unsigned int)value); return count; } #ifdef CONFIG_XFRM @@ -2373,7 +2374,7 @@ static inline int f_seen(const struct pktgen_dev *pkt= _dev, int flow) return !!(pkt_dev->flows[flow].flags & F_INIT); } =20 -static inline int f_pick(struct pktgen_dev *pkt_dev) +static inline int f_pick(struct pktgen_dev *pkt_dev, unsigned int cflows) { int flow =3D pkt_dev->curfl; =20 @@ -2383,11 +2384,11 @@ static inline int f_pick(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].count =3D 0; pkt_dev->flows[flow].flags =3D 0; pkt_dev->curfl +=3D 1; - if (pkt_dev->curfl >=3D pkt_dev->cflows) + if (pkt_dev->curfl >=3D cflows) pkt_dev->curfl =3D 0; /*reset */ } } else { - flow =3D get_random_u32_below(pkt_dev->cflows); + flow =3D get_random_u32_below(cflows); pkt_dev->curfl =3D flow; =20 if (pkt_dev->flows[flow].count > pkt_dev->lflow) { @@ -2461,12 +2462,14 @@ static void set_cur_queue_map(struct pktgen_dev *pk= t_dev) */ static void mod_cur_headers(struct pktgen_dev *pkt_dev) { + unsigned int cflows; __u32 imn; __u32 imx; int flow =3D 0; =20 - if (pkt_dev->cflows) - flow =3D f_pick(pkt_dev); + cflows =3D READ_ONCE(pkt_dev->cflows); + if (cflows) + flow =3D f_pick(pkt_dev, cflows); =20 /* Deal with source MAC */ if (pkt_dev->src_mac_count > 1) { @@ -2582,7 +2585,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_de= v) pkt_dev->cur_saddr =3D htonl(t); } =20 - if (pkt_dev->cflows && f_seen(pkt_dev, flow)) { + if (cflows && f_seen(pkt_dev, flow)) { pkt_dev->cur_daddr =3D pkt_dev->flows[flow].cur_daddr; } else { imn =3D ntohl(pkt_dev->daddr_min); @@ -2611,7 +2614,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_de= v) pkt_dev->cur_daddr =3D htonl(t); } } - if (pkt_dev->cflows) { + if (cflows) { pkt_dev->flows[flow].flags |=3D F_INIT; pkt_dev->flows[flow].cur_daddr =3D pkt_dev->cur_daddr; --=20 2.25.1