git: b483b6b256b2 - main - cxgbe tom: Force unsigned modulus for queue indices.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 05 May 2022 23:30:24 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=b483b6b256b2957f857db9092ef3c420a5143972

commit b483b6b256b2957f857db9092ef3c420a5143972
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-05-04 22:59:44 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-05-05 23:30:14 +0000

    cxgbe tom: Force unsigned modulus for queue indices.
    
    The final transmit and receive queue indices need to be positive
    values.  However, since txq_idx and rxq_idx are signed (to permit
    using -1 to as a marker for uninitialized values), using %= with
    another integer type (vi->nofld[tr]xq) yielded a sign-extended modulus
    value.  This resulted in negative queue indices and a buffer underrun
    when arc4random() returned a value with the sign bit set.  Use a
    temporary unsigned variable to hold the "raw" queue index to force
    unsigned modulus.
    
    This worked previously because the modulus was previously applied
    directly to the return value of arc4random() which is unsigned before
    the result was assigned to txq_idx and rxq_idx.
    
    Discussed with: np
    Fixes:          db28d4a0cd1c cxgbe/t4_tom: Support for round-robin selection of offload queues.
    Sponsored by:   Chelsio Communications
---
 sys/dev/cxgbe/tom/t4_tom.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 3c1554a8eaf3..9bd6145c9acc 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -1294,6 +1294,7 @@ init_conn_params(struct vi_info *vi , struct offload_settings *s,
 	struct inpcb *inp = sotoinpcb(so);
 	struct tcpcb *tp = intotcpcb(inp);
 	u_long wnd;
+	u_int q_idx;
 
 	MPASS(s->offload != 0);
 
@@ -1378,23 +1379,21 @@ init_conn_params(struct vi_info *vi , struct offload_settings *s,
 
 	/* Tx queue for this connection. */
 	if (s->txq == QUEUE_RANDOM)
-		cp->txq_idx = arc4random();
+		q_idx = arc4random();
 	else if (s->txq == QUEUE_ROUNDROBIN)
-		cp->txq_idx = atomic_fetchadd_int(&vi->txq_rr, 1);
+		q_idx = atomic_fetchadd_int(&vi->txq_rr, 1);
 	else
-		cp->txq_idx = s->txq;
-	cp->txq_idx %= vi->nofldtxq;
-	cp->txq_idx += vi->first_ofld_txq;
+		q_idx = s->txq;
+	cp->txq_idx = vi->first_ofld_txq + q_idx % vi->nofldtxq;
 
 	/* Rx queue for this connection. */
 	if (s->rxq == QUEUE_RANDOM)
-		cp->rxq_idx = arc4random();
+		q_idx = arc4random();
 	else if (s->rxq == QUEUE_ROUNDROBIN)
-		cp->rxq_idx = atomic_fetchadd_int(&vi->rxq_rr, 1);
+		q_idx = atomic_fetchadd_int(&vi->rxq_rr, 1);
 	else
-		cp->rxq_idx = s->rxq;
-	cp->rxq_idx %= vi->nofldrxq;
-	cp->rxq_idx += vi->first_ofld_rxq;
+		q_idx = s->rxq;
+	cp->rxq_idx = vi->first_ofld_rxq + q_idx % vi->nofldrxq;
 
 	if (SOLISTENING(so)) {
 		/* Passive open */