Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b31da50f authored by Tho Vu's avatar Tho Vu Committed by Greg Kroah-Hartman
Browse files

ravb: Fix use-after-free ravb_tstamp_skb



[ Upstream commit cfef46d692efd852a0da6803f920cc756eea2855 ]

When a Tx timestamp is requested, a pointer to the skb is stored in the
ravb_tstamp_skb struct. This was done without an skb_get. There exists
the possibility that the skb could be freed by ravb_tx_free (when
ravb_tx_free is called from ravb_start_xmit) before the timestamp was
processed, leading to a use-after-free bug.

Use skb_get when filling a ravb_tstamp_skb struct, and add appropriate
frees/consumes when a ravb_tstamp_skb struct is freed.

Fixes: c156633f ("Renesas Ethernet AVB driver proper")
Signed-off-by: default avatarTho Vu <tho.vu.wh@rvc.renesas.com>
Signed-off-by: default avatarKazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
Signed-off-by: default avatarSimon Horman <horms+renesas@verge.net.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 102a39cb
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
/* Renesas Ethernet AVB device driver
 *
 * Copyright (C) 2014-2015 Renesas Electronics Corporation
 * Copyright (C) 2014-2019 Renesas Electronics Corporation
 * Copyright (C) 2015 Renesas Solutions Corp.
 * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
 *
@@ -512,7 +512,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
			kfree(ts_skb);
			if (tag == tfa_tag) {
				skb_tstamp_tx(skb, &shhwtstamps);
				dev_consume_skb_any(skb);
				break;
			} else {
				dev_kfree_skb_any(skb);
			}
		}
		ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
@@ -1537,7 +1540,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
					 DMA_TO_DEVICE);
			goto unmap;
		}
		ts_skb->skb = skb;
		ts_skb->skb = skb_get(skb);
		ts_skb->tag = priv->ts_skb_tag++;
		priv->ts_skb_tag &= 0x3ff;
		list_add_tail(&ts_skb->list, &priv->ts_skb_list);
@@ -1665,6 +1668,7 @@ static int ravb_close(struct net_device *ndev)
	/* Clear the timestamp list */
	list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
		list_del(&ts_skb->list);
		kfree_skb(ts_skb->skb);
		kfree(ts_skb);
	}