]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 5.2
authorSasha Levin <sashal@kernel.org>
Thu, 5 Sep 2019 08:38:51 +0000 (04:38 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 5 Sep 2019 08:38:51 +0000 (04:38 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.2/hsr-fix-a-null-pointer-deref-in-hsr_dev_xmit.patch [new file with mode: 0644]
queue-5.2/hsr-switch-dellink-to-ndo_uninit.patch [new file with mode: 0644]
queue-5.2/series

diff --git a/queue-5.2/hsr-fix-a-null-pointer-deref-in-hsr_dev_xmit.patch b/queue-5.2/hsr-fix-a-null-pointer-deref-in-hsr_dev_xmit.patch
new file mode 100644 (file)
index 0000000..07e7d63
--- /dev/null
@@ -0,0 +1,86 @@
+From ca9e700326e2a1498f5c2fcfe1e4a8b4155eeb02 Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Wed, 3 Jul 2019 17:21:14 -0700
+Subject: hsr: fix a NULL pointer deref in hsr_dev_xmit()
+
+[ Upstream commit edf070a0fb45ac845f534baf172fbadbeb5048c6 ]
+
+hsr_port_get_hsr() could return NULL and kernel
+could crash:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000010
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 8000000074b84067 P4D 8000000074b84067 PUD 7057d067 PMD 0
+ Oops: 0000 [#1] SMP PTI
+ CPU: 0 PID: 754 Comm: a.out Not tainted 5.2.0-rc6+ #718
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
+ RIP: 0010:hsr_dev_xmit+0x20/0x31
+ Code: 48 8b 1b eb e0 5b 5d 41 5c c3 66 66 66 66 90 55 48 89 fd 48 8d be 40 0b 00 00 be 04 00 00 00 e8 ee f2 ff ff 48 89 ef 48 89 c6 <48> 8b 40 10 48 89 45 10 e8 6c 1b 00 00 31 c0 5d c3 66 66 66 66 90
+ RSP: 0018:ffffb5b400003c48 EFLAGS: 00010246
+ RAX: 0000000000000000 RBX: ffff9821b4509a88 RCX: 0000000000000000
+ RDX: ffff9821b4509a88 RSI: 0000000000000000 RDI: ffff9821bc3fc7c0
+ RBP: ffff9821bc3fc7c0 R08: 0000000000000000 R09: 00000000000c2019
+ R10: 0000000000000000 R11: 0000000000000002 R12: ffff9821bc3fc7c0
+ R13: ffff9821b4509a88 R14: 0000000000000000 R15: 000000000000006e
+ FS:  00007fee112a1800(0000) GS:ffff9821bd800000(0000) knlGS:0000000000000000
+ CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 0000000000000010 CR3: 000000006e9ce000 CR4: 00000000000406f0
+ Call Trace:
+  <IRQ>
+  netdev_start_xmit+0x1b/0x38
+  dev_hard_start_xmit+0x121/0x21e
+  ? validate_xmit_skb.isra.0+0x19/0x1e3
+  __dev_queue_xmit+0x74c/0x823
+  ? lockdep_hardirqs_on+0x12b/0x17d
+  ip6_finish_output2+0x3d3/0x42c
+  ? ip6_mtu+0x55/0x5c
+  ? mld_sendpack+0x191/0x229
+  mld_sendpack+0x191/0x229
+  mld_ifc_timer_expire+0x1f7/0x230
+  ? mld_dad_timer_expire+0x58/0x58
+  call_timer_fn+0x12e/0x273
+  __run_timers.part.0+0x174/0x1b5
+  ? mld_dad_timer_expire+0x58/0x58
+  ? sched_clock_cpu+0x10/0xad
+  ? mark_lock+0x26/0x1f2
+  ? __lock_is_held+0x40/0x71
+  run_timer_softirq+0x26/0x48
+  __do_softirq+0x1af/0x392
+  irq_exit+0x53/0xa2
+  smp_apic_timer_interrupt+0x1c4/0x1d9
+  apic_timer_interrupt+0xf/0x20
+  </IRQ>
+
+Cc: Arvid Brodin <arvid.brodin@alten.se>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_device.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
+index e6e3a7a1e3d4c..05ac0eaa72c4e 100644
+--- a/net/hsr/hsr_device.c
++++ b/net/hsr/hsr_device.c
+@@ -227,9 +227,13 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+       struct hsr_port *master;
+       master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
+-      skb->dev = master->dev;
+-      hsr_forward_skb(skb, master);
+-
++      if (master) {
++              skb->dev = master->dev;
++              hsr_forward_skb(skb, master);
++      } else {
++              atomic_long_inc(&dev->tx_dropped);
++              dev_kfree_skb_any(skb);
++      }
+       return NETDEV_TX_OK;
+ }
+-- 
+2.20.1
+
diff --git a/queue-5.2/hsr-switch-dellink-to-ndo_uninit.patch b/queue-5.2/hsr-switch-dellink-to-ndo_uninit.patch
new file mode 100644 (file)
index 0000000..0f36f5d
--- /dev/null
@@ -0,0 +1,119 @@
+From 7c46418f8ce18ac0d6ec787ee0e398119d615228 Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Tue, 9 Jul 2019 23:24:54 -0700
+Subject: hsr: switch ->dellink() to ->ndo_uninit()
+
+[ Upstream commit 311633b604063a8a5d3fbc74d0565b42df721f68 ]
+
+Switching from ->priv_destructor to dellink() has an unexpected
+consequence: existing RCU readers, that is, hsr_port_get_hsr()
+callers, may still be able to read the port list.
+
+Instead of checking the return value of each hsr_port_get_hsr(),
+we can just move it to ->ndo_uninit() which is called after
+device unregister and synchronize_net(), and we still have RTNL
+lock there.
+
+Fixes: b9a1e627405d ("hsr: implement dellink to clean up resources")
+Fixes: edf070a0fb45 ("hsr: fix a NULL pointer deref in hsr_dev_xmit()")
+Reported-by: syzbot+097ef84cdc95843fbaa8@syzkaller.appspotmail.com
+Cc: Arvid Brodin <arvid.brodin@alten.se>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_device.c  | 18 ++++++++----------
+ net/hsr/hsr_device.h  |  1 -
+ net/hsr/hsr_netlink.c |  7 -------
+ 3 files changed, 8 insertions(+), 18 deletions(-)
+
+diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
+index 05ac0eaa72c4e..08c02dbb3d695 100644
+--- a/net/hsr/hsr_device.c
++++ b/net/hsr/hsr_device.c
+@@ -227,13 +227,8 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+       struct hsr_port *master;
+       master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
+-      if (master) {
+-              skb->dev = master->dev;
+-              hsr_forward_skb(skb, master);
+-      } else {
+-              atomic_long_inc(&dev->tx_dropped);
+-              dev_kfree_skb_any(skb);
+-      }
++      skb->dev = master->dev;
++      hsr_forward_skb(skb, master);
+       return NETDEV_TX_OK;
+ }
+@@ -348,7 +343,11 @@ static void hsr_announce(struct timer_list *t)
+       rcu_read_unlock();
+ }
+-void hsr_dev_destroy(struct net_device *hsr_dev)
++/* This has to be called after all the readers are gone.
++ * Otherwise we would have to check the return value of
++ * hsr_port_get_hsr().
++ */
++static void hsr_dev_destroy(struct net_device *hsr_dev)
+ {
+       struct hsr_priv *hsr;
+       struct hsr_port *port;
+@@ -363,8 +362,6 @@ void hsr_dev_destroy(struct net_device *hsr_dev)
+       del_timer_sync(&hsr->prune_timer);
+       del_timer_sync(&hsr->announce_timer);
+-      synchronize_rcu();
+-
+       hsr_del_self_node(&hsr->self_node_db);
+       hsr_del_nodes(&hsr->node_db);
+ }
+@@ -375,6 +372,7 @@ static const struct net_device_ops hsr_device_ops = {
+       .ndo_stop = hsr_dev_close,
+       .ndo_start_xmit = hsr_dev_xmit,
+       .ndo_fix_features = hsr_fix_features,
++      .ndo_uninit = hsr_dev_destroy,
+ };
+ static struct device_type hsr_type = {
+diff --git a/net/hsr/hsr_device.h b/net/hsr/hsr_device.h
+index d0fa6b0696d25..6d7759c4f5f98 100644
+--- a/net/hsr/hsr_device.h
++++ b/net/hsr/hsr_device.h
+@@ -14,7 +14,6 @@
+ void hsr_dev_setup(struct net_device *dev);
+ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
+                    unsigned char multicast_spec, u8 protocol_version);
+-void hsr_dev_destroy(struct net_device *hsr_dev);
+ void hsr_check_carrier_and_operstate(struct hsr_priv *hsr);
+ bool is_hsr_master(struct net_device *dev);
+ int hsr_get_max_mtu(struct hsr_priv *hsr);
+diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
+index 160edd24de4e2..8f8337f893bad 100644
+--- a/net/hsr/hsr_netlink.c
++++ b/net/hsr/hsr_netlink.c
+@@ -69,12 +69,6 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
+       return hsr_dev_finalize(dev, link, multicast_spec, hsr_version);
+ }
+-static void hsr_dellink(struct net_device *hsr_dev, struct list_head *head)
+-{
+-      hsr_dev_destroy(hsr_dev);
+-      unregister_netdevice_queue(hsr_dev, head);
+-}
+-
+ static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ {
+       struct hsr_priv *hsr;
+@@ -119,7 +113,6 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
+       .priv_size      = sizeof(struct hsr_priv),
+       .setup          = hsr_dev_setup,
+       .newlink        = hsr_newlink,
+-      .dellink        = hsr_dellink,
+       .fill_info      = hsr_fill_info,
+ };
+-- 
+2.20.1
+
index 5b3c63225176dcaf08b7d7a5a909abaf1ffe4de1..84dd483a8083241ee9fef9c114710605ad4740b6 100644 (file)
@@ -141,3 +141,5 @@ drm-i915-dp-fix-dsc-enable-code-to-use-cpu_transcode.patch
 x86-ptrace-fix-up-botched-merge-of-spectrev1-fix.patch
 bpf-fix-use-after-free-in-prog-symbol-exposure.patch
 hsr-implement-dellink-to-clean-up-resources.patch
+hsr-fix-a-null-pointer-deref-in-hsr_dev_xmit.patch
+hsr-switch-dellink-to-ndo_uninit.patch