Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ravb: Fix use-after-free ravb_tstamp_skb

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: c156633f1353 ("Renesas Ethernet AVB driver proper")
Signed-off-by: Tho Vu <tho.vu.wh@rvc.renesas.com>
Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tho Vu and committed by
David S. Miller
cfef46d6 5cbe9102

+6 -2
+6 -2
drivers/net/ethernet/renesas/ravb_main.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Renesas Ethernet AVB device driver 3 3 * 4 - * Copyright (C) 2014-2015 Renesas Electronics Corporation 4 + * Copyright (C) 2014-2019 Renesas Electronics Corporation 5 5 * Copyright (C) 2015 Renesas Solutions Corp. 6 6 * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com> 7 7 * ··· 513 513 kfree(ts_skb); 514 514 if (tag == tfa_tag) { 515 515 skb_tstamp_tx(skb, &shhwtstamps); 516 + dev_consume_skb_any(skb); 516 517 break; 518 + } else { 519 + dev_kfree_skb_any(skb); 517 520 } 518 521 } 519 522 ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR); ··· 1567 1564 } 1568 1565 goto unmap; 1569 1566 } 1570 - ts_skb->skb = skb; 1567 + ts_skb->skb = skb_get(skb); 1571 1568 ts_skb->tag = priv->ts_skb_tag++; 1572 1569 priv->ts_skb_tag &= 0x3ff; 1573 1570 list_add_tail(&ts_skb->list, &priv->ts_skb_list); ··· 1696 1693 /* Clear the timestamp list */ 1697 1694 list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { 1698 1695 list_del(&ts_skb->list); 1696 + kfree_skb(ts_skb->skb); 1699 1697 kfree(ts_skb); 1700 1698 } 1701 1699