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: c156633f13
("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>
This commit is contained in:
parent
5cbe9102ae
commit
cfef46d692
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/* Renesas Ethernet AVB device driver
|
/* 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 Renesas Solutions Corp.
|
||||||
* Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
|
* Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
|
||||||
*
|
*
|
||||||
|
@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
|
||||||
kfree(ts_skb);
|
kfree(ts_skb);
|
||||||
if (tag == tfa_tag) {
|
if (tag == tfa_tag) {
|
||||||
skb_tstamp_tx(skb, &shhwtstamps);
|
skb_tstamp_tx(skb, &shhwtstamps);
|
||||||
|
dev_consume_skb_any(skb);
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
|
ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
|
||||||
|
@ -1564,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||||
}
|
}
|
||||||
goto unmap;
|
goto unmap;
|
||||||
}
|
}
|
||||||
ts_skb->skb = skb;
|
ts_skb->skb = skb_get(skb);
|
||||||
ts_skb->tag = priv->ts_skb_tag++;
|
ts_skb->tag = priv->ts_skb_tag++;
|
||||||
priv->ts_skb_tag &= 0x3ff;
|
priv->ts_skb_tag &= 0x3ff;
|
||||||
list_add_tail(&ts_skb->list, &priv->ts_skb_list);
|
list_add_tail(&ts_skb->list, &priv->ts_skb_list);
|
||||||
|
@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev)
|
||||||
/* Clear the timestamp list */
|
/* Clear the timestamp list */
|
||||||
list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
|
list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
|
||||||
list_del(&ts_skb->list);
|
list_del(&ts_skb->list);
|
||||||
|
kfree_skb(ts_skb->skb);
|
||||||
kfree(ts_skb);
|
kfree(ts_skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue