net: stmmac: WARN if tx_skbuff entries are reused before cleared
authorNiklas Cassel <niklas.cassel@axis.com>
Mon, 19 Feb 2018 17:11:11 +0000 (18:11 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Feb 2018 19:13:18 +0000 (14:13 -0500)
The current code assumes that a tx_skbuff entry has been cleared
by stmmac_tx_clean() before stmmac_xmit()/stmmac_tso_xmit()
assigns a new skb to that entry. However, since we never check
the current value before overwriting it, it is theoretically
possible that a non-NULL value is overwritten.

Add WARN_ONs to verify that each entry in tx_skbuff is NULL
before it is assigned a new value.

Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 24afe7733cde6c207545bb1af0a8263df9e1b6e5..9881df1262278ec646b4ec33076a86a0dc0bf6ef 100644 (file)
@@ -2794,6 +2794,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
 
        while (tmp_len > 0) {
                tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
+               WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
                desc = tx_q->dma_tx + tx_q->cur_tx;
 
                desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
@@ -2878,6 +2879,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
                priv->hw->desc->set_mss(mss_desc, mss);
                tx_q->mss = mss;
                tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
+               WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
        }
 
        if (netif_msg_tx_queued(priv)) {
@@ -2888,6 +2890,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        first_entry = tx_q->cur_tx;
+       WARN_ON(tx_q->tx_skbuff[first_entry]);
 
        desc = tx_q->dma_tx + first_entry;
        first = desc;
@@ -3062,6 +3065,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        entry = tx_q->cur_tx;
        first_entry = entry;
+       WARN_ON(tx_q->tx_skbuff[first_entry]);
 
        csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
 
@@ -3090,6 +3094,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                bool last_segment = (i == (nfrags - 1));
 
                entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
+               WARN_ON(tx_q->tx_skbuff[entry]);
 
                if (likely(priv->extend_desc))
                        desc = (struct dma_desc *)(tx_q->dma_etx + entry);