Module Name:    src
Committed By:   thorpej
Date:           Sun Sep 18 15:44:29 UTC 2022

Modified Files:
        src/sys/arch/arm/sunxi: sunxi_emac.c

Log Message:
Eliminate use of IFF_OACTIVE.

While here, fix a use-after-free bug in the "too many segments" error path in
sunxi_emac_setup_txbuf().


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/arm/sunxi/sunxi_emac.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/arch/arm/sunxi/sunxi_emac.c
diff -u src/sys/arch/arm/sunxi/sunxi_emac.c:1.36 src/sys/arch/arm/sunxi/sunxi_emac.c:1.37
--- src/sys/arch/arm/sunxi/sunxi_emac.c:1.36	Tue Jun 28 05:19:03 2022
+++ src/sys/arch/arm/sunxi/sunxi_emac.c	Sun Sep 18 15:44:29 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_emac.c,v 1.36 2022/06/28 05:19:03 skrll Exp $ */
+/* $NetBSD: sunxi_emac.c,v 1.37 2022/09/18 15:44:29 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2016-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -33,7 +33,7 @@
 #include "opt_net_mpsafe.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.36 2022/06/28 05:19:03 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.37 2022/09/18 15:44:29 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -351,8 +351,8 @@ sunxi_emac_setup_txbuf(struct sunxi_emac
 	if (error == EFBIG) {
 		device_printf(sc->dev,
 		    "TX packet needs too many DMA segments, dropping...\n");
-		m_freem(m);
-		return 0;
+		/* Caller will dequeue and free packet. */
+		return -1;
 	}
 	if (error != 0)
 		return 0;
@@ -447,12 +447,11 @@ sunxi_emac_start_locked(struct sunxi_ema
 
 	EMAC_ASSERT_LOCKED(sc);
 
-	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+	if ((ifp->if_flags & IFF_RUNNING) == 0)
 		return;
 
 	for (cnt = 0, start = sc->tx.cur; ; cnt++) {
 		if (sc->tx.queued >= TX_DESC_COUNT - TX_MAX_SEGS) {
-			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
@@ -461,8 +460,16 @@ sunxi_emac_start_locked(struct sunxi_ema
 			break;
 
 		nsegs = sunxi_emac_setup_txbuf(sc, sc->tx.cur, m);
-		if (nsegs == 0) {
-			ifp->if_flags |= IFF_OACTIVE;
+		if (__predict_false(nsegs <= 0)) {
+			if (nsegs == -1) {
+				/*
+				 * We're being asked to discard this packet,
+				 * but we can try to continue.
+				 */
+				IFQ_DEQUEUE(&ifp->if_snd, m);
+				m_freem(m);
+				continue;
+			}
 			break;
 		}
 		IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -702,7 +709,6 @@ sunxi_emac_init_locked(struct sunxi_emac
 	WR4(sc, EMAC_RX_CTL_0, val | RX_EN | CHECK_CRC);
 
 	ifp->if_flags |= IFF_RUNNING;
-	ifp->if_flags &= ~IFF_OACTIVE;
 
 	mii_mediachg(mii);
 	callout_schedule(&sc->stat_ch, hz);
@@ -760,7 +766,7 @@ sunxi_emac_stop_locked(struct sunxi_emac
 	val = RD4(sc, EMAC_RX_CTL_1);
 	WR4(sc, EMAC_RX_CTL_1, val & ~RX_DMA_EN);
 
-	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+	ifp->if_flags &= ~IFF_RUNNING;
 }
 
 static void
@@ -876,7 +882,6 @@ sunxi_emac_txintr(struct sunxi_emac_soft
 		    i, i + 1, TX_DESC_COUNT,
 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-		ifp->if_flags &= ~IFF_OACTIVE;
 		if_statinc(ifp, if_opackets);
 	}
 

Reply via email to