Re: [PATCH net] net: pktgen: use a consistent flow count

Paolo Abeni <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
On 8/2/26 5:23 PM, Qi Zhang wrote:
> From: Chengfeng Ye <[email protected]>
> 
> 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 = 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:
>    <TASK>
>    pktgen_thread_worker+0x305a/0x6bc0
>    kthread+0x2c6/0x3b0
>    ret_from_fork+0x36e/0x5a0
>    ret_from_fork_asm+0x1a/0x30
>    </TASK>
> 
> 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: [email protected]
> Signed-off-by: Chengfeng Ye <[email protected]>
> Signed-off-by: Qi Zhang <[email protected]>
> ---
>  net/core/pktgen.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> index ee64f3012321..631cb1f55f6d 100644
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -1632,7 +1632,7 @@ static ssize_t pktgen_if_write(struct file *file,
>  		if (value > MAX_CFLOWS)
>  			value = MAX_CFLOWS;
>  
> -		pkt_dev->cflows = value;
> +		WRITE_ONCE(pkt_dev->cflows, value);
>  		sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);

Please use:
		sprintf(pg_result, "OK: flows=%u", value);

so that the user get consistent results across racing writes.

Also you need to add READ_ONCE() annotation to all `->cflows` accesses -
a few missed ones in pktgen_if_show().

/P
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.