diff options
author | Tho Vu <tho.vu.wh@rvc.renesas.com> | 2018-12-13 10:04:56 +0100 |
---|---|---|
committer | Ryo Kataoka <ryo.kataoka.wt@renesas.com> | 2019-03-22 20:50:16 +0900 |
commit | 444401e833c4ad6258210713bc656a733f7c4de7 (patch) | |
tree | 37fab51154d98dc21505f57edf087d6ae734e550 | |
parent | a9580312f193558476af176c19090b2ad33a90a5 (diff) | |
download | renesas-bsp-444401e833c4ad6258210713bc656a733f7c4de7.tar.gz |
ravb: Fix use-after-free ravb_tstamp_skb
This patch is used for fixing kernel crash caused by ethernet driver
Crash:
Unable to handle kernel paging request at virtual address 7000000000000
[0007000000000000] address between user and kernel address ranges
Internal error: Oops: 96000004 [#1] PREEMPT SMP
CPU: 0 PID: 2500 Comm: m3.reader Tainted: P O 4.14.35-yocto-standard #1
task: ffffffc648f0f080 task.stack: ffffff80229d8000
PC is at kfree_skb_list+0x14/0x30
LR is at skb_release_data+0x44/0x12c
Call trace:
Exception stack
...
kfree_skb_list+0x14/0x30
skb_release_data+0x44/0x12c
skb_release_all+0x24/0x30
__kfree_skb+0x14/0x28
consume_skb+0xe4/0xf0
__dev_kfree_skb_any+0x38/0x3c
switch_ptp_endpoint_tx+0x1fc/0x1560 [ptp_broker]
sock_queue_err_skb+0xf0/0x12c
__skb_complete_tx_timestamp+0x98/0xb8
__skb_tstamp_tx+0xb8/0x18c
skb_tstamp_tx+0x14/0x1c
ravb_poll+0x67c/0x6dc [ravb]
net_rx_action+0x12c/0x33c
__do_softirq+0x298/0x348
irq_exit+0x74/0xbc
__handle_domain_irq+0x78/0xac
gic_handle_irq+0x80/0xac
Exception stack
el0_irq_naked+0x44/0x4c
Kernel panic - not syncing: Fatal exception in interrupt
Kernel Offset: disabled
CPU features: 0x0802004
---[ end Kernel panic - not syncing: Fatal exception in interrupt
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.
Signed-off-by: Tho Vu <tho.vu.wh@rvc.renesas.com>
Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
-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 839e473f7fc49..fa106c1c1511a 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1,6 +1,6 @@ /* Renesas Ethernet AVB device driver * - * Copyright (C) 2014-2017 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> * @@ -516,7 +516,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); @@ -1541,7 +1544,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) } 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); @@ -1663,6 +1666,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); } |