aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTho Vu <tho.vu.wh@rvc.renesas.com>2018-12-13 10:04:56 +0100
committerRyo Kataoka <ryo.kataoka.wt@renesas.com>2019-03-22 20:50:16 +0900
commit444401e833c4ad6258210713bc656a733f7c4de7 (patch)
tree37fab51154d98dc21505f57edf087d6ae734e550
parenta9580312f193558476af176c19090b2ad33a90a5 (diff)
downloadrenesas-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.c8
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);
}