Commit c71e3a5c authored by Ken Milmore's avatar Ken Milmore Committed by Paolo Abeni

r8169: Fix possible ring buffer corruption on fragmented Tx packets.

An issue was found on the RTL8125b when transmitting small fragmented
packets, whereby invalid entries were inserted into the transmit ring
buffer, subsequently leading to calls to dma_unmap_single() with a null
address.

This was caused by rtl8169_start_xmit() not noticing changes to nr_frags
which may occur when small packets are padded (to work around hardware
quirks) in rtl8169_tso_csum_v2().

To fix this, postpone inspecting nr_frags until after any padding has been
applied.

Fixes: 9020845f ("r8169: improve rtl8169_start_xmit")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarKen Milmore <ken.milmore@gmail.com>
Reviewed-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/27ead18b-c23d-4f49-a020-1fc482c5ac95@gmail.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 3d8597d8
...@@ -4337,11 +4337,11 @@ static void rtl8169_doorbell(struct rtl8169_private *tp) ...@@ -4337,11 +4337,11 @@ static void rtl8169_doorbell(struct rtl8169_private *tp)
static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
unsigned int frags = skb_shinfo(skb)->nr_frags;
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
unsigned int entry = tp->cur_tx % NUM_TX_DESC; unsigned int entry = tp->cur_tx % NUM_TX_DESC;
struct TxDesc *txd_first, *txd_last; struct TxDesc *txd_first, *txd_last;
bool stop_queue, door_bell; bool stop_queue, door_bell;
unsigned int frags;
u32 opts[2]; u32 opts[2];
if (unlikely(!rtl_tx_slots_avail(tp))) { if (unlikely(!rtl_tx_slots_avail(tp))) {
...@@ -4364,6 +4364,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, ...@@ -4364,6 +4364,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
txd_first = tp->TxDescArray + entry; txd_first = tp->TxDescArray + entry;
frags = skb_shinfo(skb)->nr_frags;
if (frags) { if (frags) {
if (rtl8169_xmit_frags(tp, skb, opts, entry)) if (rtl8169_xmit_frags(tp, skb, opts, entry))
goto err_dma_1; goto err_dma_1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment