Module Name:    src
Committed By:   msaitoh
Date:           Tue Jul 30 04:42:29 UTC 2019

Modified Files:
        src/sys/dev/pci: if_wm.c

Log Message:
- rnd_add_*() call must be serialized. Unserialized accesses broke the
  sc->rnd_source structure and caused off by one in kern_rndq.c's
  rnd_add_data_ts(). This problem was found by kUBSan. Make krndsource_t's
  data per queue-pair and call rnd_add_uint32() in wm_txrxintr_msix(). One of
  the reason why rnd_add_uint32() calls were moved from wm_{tx,rx}eof() is that
  rnd(9) manual page says "To allow the system to gather the timing information
  accurately, this call should be placed within the actual hardware interrupt
  service routine."
- Pass a better value to rnd_add_uint32() in wm_intr_legacy().

XXX pullup-8.


To generate a diff of this commit:
cvs rdiff -u -r1.644 -r1.645 src/sys/dev/pci/if_wm.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.644 src/sys/dev/pci/if_wm.c:1.645
--- src/sys/dev/pci/if_wm.c:1.644	Fri Jul 26 09:26:56 2019
+++ src/sys/dev/pci/if_wm.c	Tue Jul 30 04:42:29 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.644 2019/07/26 09:26:56 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.645 2019/07/30 04:42:29 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.644 2019/07/26 09:26:56 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.645 2019/07/30 04:42:29 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -234,7 +234,7 @@ static int wm_watchdog_timeout = WM_WATC
  * packet.  We allocate 256 receive descriptors, each with a 2k
  * buffer (MCLBYTES), which gives us room for 50 jumbo packets.
  */
-#define	WM_NRXDESC		256
+#define	WM_NRXDESC		256U
 #define	WM_NRXDESC_MASK		(WM_NRXDESC - 1)
 #define	WM_NEXTRX(x)		(((x) + 1) & WM_NRXDESC_MASK)
 #define	WM_PREVRX(x)		(((x) - 1) & WM_NRXDESC_MASK)
@@ -458,6 +458,7 @@ struct wm_queue {
 	struct wm_rxqueue wmq_rxq;
 
 	void *wmq_si;
+	krndsource_t rnd_source;	/* random source */
 };
 
 struct wm_phyop {
@@ -587,8 +588,6 @@ struct wm_softc {
 
 	int sc_mchash_type;		/* multicast filter offset */
 
-	krndsource_t rnd_source;	/* random source */
-
 	struct if_percpuq *sc_ipq;	/* softint-based input queues */
 
 	kmutex_t *sc_core_lock;		/* lock for softc operations */
@@ -2956,8 +2955,6 @@ alloc_retry:
 	ether_ifattach(ifp, enaddr);
 	ether_set_ifflags_cb(&sc->sc_ethercom, wm_ifflags_cb);
 	if_register(ifp);
-	rnd_attach_source(&sc->rnd_source, xname, RND_TYPE_NET,
-	    RND_FLAG_DEFAULT);
 
 #ifdef WM_EVENT_COUNTERS
 	/* Attach event counters. */
@@ -3012,8 +3009,6 @@ wm_detach(device_t self, int flags __unu
 	evcnt_detach(&sc->sc_ev_rx_macctl);
 #endif /* WM_EVENT_COUNTERS */
 
-	rnd_detach_source(&sc->rnd_source);
-
 	/* Tell the firmware about the release */
 	WM_CORE_LOCK(sc);
 	wm_release_manageability(sc);
@@ -6831,6 +6826,15 @@ wm_alloc_txrx_queues(struct wm_softc *sc
 	if (error)
 		goto fail_2;
 
+	for (i = 0; i < sc->sc_nqueues; i++) {
+		char rndname[16];
+
+		snprintf(rndname, sizeof(rndname), "%sTXRX%d",
+		    device_xname(sc->sc_dev), i);
+		rnd_attach_source(&sc->sc_queue[i].rnd_source, rndname,
+		    RND_TYPE_NET, RND_FLAG_DEFAULT);
+	}
+
 	return 0;
 
  fail_2:
@@ -6866,6 +6870,9 @@ wm_free_txrx_queues(struct wm_softc *sc)
 {
 	int i;
 
+	for (i = 0; i < sc->sc_nqueues; i++)
+		rnd_detach_source(&sc->sc_queue[i].rnd_source);
+
 	for (i = 0; i < sc->sc_nqueues; i++) {
 		struct wm_rxqueue *rxq = &sc->sc_queue[i].wmq_rxq;
 
@@ -8532,9 +8539,6 @@ wm_txeof(struct wm_txqueue *txq, u_int l
 	DPRINTF(WM_DEBUG_TX,
 	    ("%s: TX: txsdirty -> %d\n", device_xname(sc->sc_dev), i));
 
-	if (count != 0)
-		rnd_add_uint32(&sc->rnd_source, count);
-
 	/*
 	 * If there are no more pending transmissions, cancel the watchdog
 	 * timer.
@@ -8948,9 +8952,6 @@ wm_rxeof(struct wm_rxqueue *rxq, u_int l
 			break;
 	}
 
-	if (count != 0)
-		rnd_add_uint32(&sc->rnd_source, count);
-
 	DPRINTF(WM_DEBUG_RX,
 	    ("%s: RX: rxptr -> %d\n", device_xname(sc->sc_dev), i));
 
@@ -9416,6 +9417,8 @@ wm_intr_legacy(void *arg)
 		 * So, we can call wm_rxeof() in interrupt context.
 		 */
 		wm_rxeof(rxq, UINT_MAX);
+		/* Fill lower bits with RX index. See below for the upper. */
+		rndval |= rxq->rxq_ptr & WM_NRXDESC_MASK;
 
 		mutex_exit(rxq->rxq_lock);
 		mutex_enter(txq->txq_lock);
@@ -9434,6 +9437,8 @@ wm_intr_legacy(void *arg)
 		}
 #endif
 		wm_txeof(txq, UINT_MAX);
+		/* Fill upper bits with TX index. See above for the lower. */
+		rndval = txq->txq_next * WM_NRXDESC;
 
 		mutex_exit(txq->txq_lock);
 		WM_CORE_LOCK(sc);
@@ -9458,7 +9463,7 @@ wm_intr_legacy(void *arg)
 		}
 	}
 
-	rnd_add_uint32(&sc->rnd_source, rndval);
+	rnd_add_uint32(&sc->sc_queue[0].rnd_source, rndval);
 
 	if (handled) {
 		/* Try to get more packets going. */
@@ -9515,6 +9520,7 @@ wm_txrxintr_msix(void *arg)
 	struct wm_softc *sc = txq->txq_sc;
 	u_int txlimit = sc->sc_tx_intr_process_limit;
 	u_int rxlimit = sc->sc_rx_intr_process_limit;
+	uint32_t rndval = 0;
 	bool txmore;
 	bool rxmore;
 
@@ -9534,6 +9540,8 @@ wm_txrxintr_msix(void *arg)
 
 	WM_Q_EVCNT_INCR(txq, txdw);
 	txmore = wm_txeof(txq, txlimit);
+	/* Fill upper bits with TX index. See below for the lower. */
+	rndval = txq->txq_next * WM_NRXDESC;
 	/* wm_deferred start() is done in wm_handle_queue(). */
 	mutex_exit(txq->txq_lock);
 
@@ -9548,10 +9556,20 @@ wm_txrxintr_msix(void *arg)
 
 	WM_Q_EVCNT_INCR(rxq, intr);
 	rxmore = wm_rxeof(rxq, rxlimit);
+
+	/* Fill lower bits with RX index. See above for the upper. */
+	rndval |= rxq->rxq_ptr & WM_NRXDESC_MASK;
 	mutex_exit(rxq->rxq_lock);
 
 	wm_itrs_writereg(sc, wmq);
 
+	/*
+	 * This function is called in the hardware interrupt context and
+	 * per-CPU, so it's not required to take a lock.
+	 */
+	if (rndval != 0)
+		rnd_add_uint32(&sc->sc_queue[wmq->wmq_id].rnd_source, rndval);
+
 	if (txmore || rxmore)
 		softint_schedule(wmq->wmq_si);
 	else

Reply via email to