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); }