diff options
author | Tho Vu <tho.vu.wh@rvc.renesas.com> | 2019-08-16 11:17:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-08-18 17:19:14 -0400 |
commit | cfef46d692efd852a0da6803f920cc756eea2855 (patch) | |
tree | f3ad1784d32745cfc43bba49b78b46b88f6a674d | |
parent | 5cbe9102ae2398c0f410fd4f832d9f038e751a29 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/renesas/ravb_main.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ef8f08931fe8..6cacd5e893ac 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Renesas Ethernet AVB device driver | 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 | * Copyright (C) 2015 Renesas Solutions Corp. | 5 | * Copyright (C) 2015 Renesas Solutions Corp. |
6 | * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com> | 6 | * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com> |
7 | * | 7 | * |
@@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev) | |||
513 | kfree(ts_skb); | 513 | kfree(ts_skb); |
514 | if (tag == tfa_tag) { | 514 | if (tag == tfa_tag) { |
515 | skb_tstamp_tx(skb, &shhwtstamps); | 515 | skb_tstamp_tx(skb, &shhwtstamps); |
516 | dev_consume_skb_any(skb); | ||
516 | break; | 517 | break; |
518 | } else { | ||
519 | dev_kfree_skb_any(skb); | ||
517 | } | 520 | } |
518 | } | 521 | } |
519 | ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR); | 522 | 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) | |||
1564 | } | 1567 | } |
1565 | goto unmap; | 1568 | goto unmap; |
1566 | } | 1569 | } |
1567 | ts_skb->skb = skb; | 1570 | ts_skb->skb = skb_get(skb); |
1568 | ts_skb->tag = priv->ts_skb_tag++; | 1571 | ts_skb->tag = priv->ts_skb_tag++; |
1569 | priv->ts_skb_tag &= 0x3ff; | 1572 | priv->ts_skb_tag &= 0x3ff; |
1570 | list_add_tail(&ts_skb->list, &priv->ts_skb_list); | 1573 | list_add_tail(&ts_skb->list, &priv->ts_skb_list); |
@@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev) | |||
1693 | /* Clear the timestamp list */ | 1696 | /* Clear the timestamp list */ |
1694 | list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { | 1697 | list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { |
1695 | list_del(&ts_skb->list); | 1698 | list_del(&ts_skb->list); |
1699 | kfree_skb(ts_skb->skb); | ||
1696 | kfree(ts_skb); | 1700 | kfree(ts_skb); |
1697 | } | 1701 | } |
1698 | 1702 | ||