[Devel] [PATCH RHEL7 COMMIT] ms/vxlan: fix use-after-free on deletion
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Jun 20 20:02:07 MSK 2017
The commit is pushed to "branch-rh7-3.10.0-514.16.1.vz7.32.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.16.1.vz7.32.10
------>
commit 75ef002ea6ccedf78482e2e0972cdee8edad2da5
Author: Mark Bloch <markb at mellanox.com>
Date: Tue Jun 20 21:02:07 2017 +0400
ms/vxlan: fix use-after-free on deletion
Reproduced on debug kernel with KASAN:
[20903.934764] BUG: KASan: use after free in vxlan_dellink+0x5b2/0x5f0 [vxlan] at addr ffff880014180018
[20903.939483] Write of size 8 by task dockerd/392675
[20903.943568] page:ffffea0000506000 count:0 mapcount:-127 mapping: (null) index:0x0
[20903.948279] page flags: 0x1fffff00000000()
[20903.952357] page dumped because: kasan: bad access detected
[20903.956635] CPU: 2 PID: 392675 Comm: dockerd ve: 54366ea9-3f08-446c-a794-02b8a9176a72 Not tainted 3.10.0-514.16.1.vz7.32.7.debug #1 32.7
[20903.965876] Hardware name: Virtuozzo KVM, BIOS 1.9.1-5.3.2.vz7.6 04/01/2014
[20903.970907] ffff880014180018 00000000f359ad59 ffff8801a63d7438 ffffffff8255cce0
[20903.976184] ffff8801a63d74b8 ffffffff8162352f ffff8801a63d74a0 ffffffff8133cc11
[20903.981393] 0000000000000297 0000000000000297 ffffffffa0f4a4f2 ffff8801bbf14ce8
[20903.986748] Call Trace:
[20903.991106] [<ffffffff8255cce0>] dump_stack+0x1e/0x20
[20903.995961] [<ffffffff8162352f>] kasan_report+0x4ff/0x540
[20904.000804] [<ffffffff8133cc11>] ? lock_acquired+0x331/0xfd0
[20904.005656] [<ffffffffa0f4a4f2>] ? vxlan_dellink+0x5b2/0x5f0 [vxlan]
[20904.010856] [<ffffffff8162368c>] __asan_report_store8_noabort+0x1c/0x20
[20904.015990] [<ffffffffa0f4a4f2>] vxlan_dellink+0x5b2/0x5f0 [vxlan]
[20904.021161] [<ffffffffa0f49fd1>] ? vxlan_dellink+0x91/0x5f0 [vxlan]
[20904.026385] [<ffffffffa0f49f40>] ? vxlan_fdb_dump+0x600/0x600 [vxlan]
[20904.031598] [<ffffffff8217f9b8>] rtnl_delete_link+0xd8/0x150
[20904.036637] [<ffffffff8217f8e0>] ? __rtnl_link_unregister+0x260/0x260
[20904.041786] [<ffffffff81a4b8e2>] ? nla_parse+0x1f2/0x290
[20904.046826] [<ffffffff82182d54>] rtnl_dellink+0x244/0x300
[20904.051865] [<ffffffff82182b10>] ? rtnl_dump_all+0x3a0/0x3a0
[20904.057010] [<ffffffff811b992d>] ? ns_capable+0xbd/0x100
[20904.062182] [<ffffffff821ea0d2>] ? __netlink_ns_capable+0xe2/0x130
[20904.067412] [<ffffffff82182b10>] ? rtnl_dump_all+0x3a0/0x3a0
[20904.072582] [<ffffffff8218314a>] rtnetlink_rcv_msg+0x27a/0x770
[20904.077802] [<ffffffff82182ed0>] ? rtnetlink_rcv+0x40/0x40
[20904.082916] [<ffffffff82182eb0>] ? rtnetlink_rcv+0x20/0x40
[20904.087978] [<ffffffff821f2190>] ? netlink_connect+0x500/0x500
[20904.093052] [<ffffffff825660f0>] ? mutex_lock_interruptible_nested+0xfc0/0xfc0
[20904.098449] [<ffffffff821fca15>] netlink_rcv_skb+0x2a5/0x3a0
[20904.103574] [<ffffffff82182ed0>] ? rtnetlink_rcv+0x40/0x40
[20904.108663] [<ffffffff82182ebf>] rtnetlink_rcv+0x2f/0x40
[20904.113659] [<ffffffff821fa630>] netlink_unicast+0x420/0x4e0
[20904.118731] [<ffffffff821fa210>] ? netlink_attachskb+0x680/0x680
[20904.123814] [<ffffffff81622844>] ? kasan_check_write+0x14/0x20
[20904.128912] [<ffffffff81a03a3b>] ? memcpy_fromiovec+0x11b/0x170
[20904.133906] [<ffffffff821fb288>] netlink_sendmsg+0xb98/0x1bd0
[20904.138832] [<ffffffff81345c79>] ? lock_acquire+0x169/0x460
[20904.143832] [<ffffffff81282043>] ? rcu_read_lock+0x43/0xd0
[20904.148765] [<ffffffff821fa6f0>] ? netlink_unicast+0x4e0/0x4e0
[20904.153705] [<ffffffff81342d58>] ? __lock_acquire+0x6f8/0x2b40
[20904.158676] [<ffffffff820df2dd>] sock_sendmsg+0x13d/0x1e0
[20904.163561] [<ffffffff81342660>] ? debug_check_no_locks_freed+0x320/0x320
[20904.168663] [<ffffffff820df1a0>] ? sockfd_lookup+0x160/0x160
[20904.173451] [<ffffffff81221326>] ? __wake_up_bit+0xc6/0x110
[20904.178162] [<ffffffff81221260>] ? wait_woken+0x1d0/0x1d0
[20904.182809] [<ffffffff820e443e>] SYSC_sendto+0x22e/0x380
[20904.187373] [<ffffffff820e4210>] ? SYSC_connect+0x2e0/0x2e0
[20904.191979] [<ffffffff8168e79e>] ? fput+0x16e/0x1a0
[20904.196333] [<ffffffff815a3a10>] ? copy_page_range+0x980/0x980
[20904.200689] [<ffffffff81345c79>] ? lock_acquire+0x169/0x460
[20904.205067] [<ffffffff8122faa4>] ? up_read+0x24/0x40
[20904.209250] [<ffffffff8257e469>] ? __do_page_fault+0x1e9/0xb30
[20904.213532] [<ffffffff81348efa>] ? lockdep_sys_exit+0x4a/0x100
[20904.217749] [<ffffffff819f80c4>] ? lockdep_sys_exit_thunk+0x16/0x18
[20904.221985] [<ffffffff81333d65>] ? trace_hardirqs_off_caller+0x1e5/0x2c0
[20904.226264] [<ffffffff820e8625>] SyS_sendto+0x45/0x60
[20904.230307] [<ffffffff8258f149>] system_call_fastpath+0x16/0x1b
[20904.234467] Memory state around the buggy address:
[20904.238463] ffff88001417ff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[20904.242913] ffff88001417ff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[20904.247317] >ffff880014180000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[20904.251683] ^
[20904.255539] ffff880014180080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[20904.260011] ffff880014180100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[20904.264473] ==================================================================
In vxlan_dellink->hlist_del_rcu->__hlist_del: vxlan->hlist->pprev points to freed
memory (0xb88 is offset of pprev relative to struct net_device):
0xffffffffa0f4a17e <vxlan_dellink+574>: mov 0xb88(%r12),%r13
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/drivers/net/vxlan.c: 3105
0xffffffffa0f4a186 <vxlan_dellink+582>: test %r13,%r13
0xffffffffa0f4a189 <vxlan_dellink+585>: je 0xffffffffa0f4a23d <vxlan_dellink+765>
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/drivers/net/vxlan.c: 3106
0xffffffffa0f4a18f <vxlan_dellink+591>: callq 0xffffffff813e20a0 <__sanitizer_cov_trace_pc>
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/include/linux/list.h: 626
0xffffffffa0f4a194 <vxlan_dellink+596>: lea 0xb80(%r12),%rdi
0xffffffffa0f4a19c <vxlan_dellink+604>: movabs $0xdffffc0000000000,%rax
0xffffffffa0f4a1a6 <vxlan_dellink+614>: mov %rdi,%rdx
0xffffffffa0f4a1a9 <vxlan_dellink+617>: shr $0x3,%rdx
0xffffffffa0f4a1ad <vxlan_dellink+621>: cmpb $0x0,(%rdx,%rax,1)
0xffffffffa0f4a1b1 <vxlan_dellink+625>: jne 0xffffffffa0f4a4f7 <vxlan_dellink+1463>
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/include/linux/list.h: 628
0xffffffffa0f4a1b7 <vxlan_dellink+631>: mov %r13,%rdx
0xffffffffa0f4a1ba <vxlan_dellink+634>: movabs $0xdffffc0000000000,%rax
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/include/linux/list.h: 626
0xffffffffa0f4a1c4 <vxlan_dellink+644>: mov 0xb80(%r12),%r15
/usr/src/debug/kernel-3.10.0-514.16.1.el7/linux-3.10.0-514.16.1.vz7.32.7/include/linux/list.h: 628
0xffffffffa0f4a1cc <vxlan_dellink+652>: shr $0x3,%rdx
0xffffffffa0f4a1d0 <vxlan_dellink+656>: cmpb $0x0,(%rdx,%rax,1)
0xffffffffa0f4a1d4 <vxlan_dellink+660>: jne 0xffffffffa0f4a4ea <vxlan_dellink+1450>
0xffffffffa0f4a4ea <vxlan_dellink+1450>: mov %r13,%rdi
0xffffffffa0f4a4ed <vxlan_dellink+1453>: callq 0xffffffff81623670 <__asan_report_store8_noabort>
0xffffffffa0f4a4f2 <vxlan_dellink+1458>: jmpq 0xffffffffa0f4a1da <vxlan_dellink+666>
https://jira.sw.ru/browse/PSBM-67263
Adding a vxlan interface to a socket isn't symmetrical, while adding
is done in vxlan_open() the deletion is done in vxlan_dellink().
This can cause a use-after-free error when we close the vxlan
interface before deleting it.
We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call
it from vxlan_stop() to match the call from vxlan_open().
Fixes: 56ef9c909b40 ("vxlan: Move socket initialization to within rtnl scope")
Acked-by: Jiri Benc <jbenc at redhat.com>
Tested-by: Roi Dayan <roid at mellanox.com>
Signed-off-by: Mark Bloch <markb at mellanox.com>
Acked-by: Roopa Prabhu <roopa at cumulusnetworks.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
drivers/net/vxlan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 5670d15..ec3a83b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -77,6 +77,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2];
static int vxlan_sock_add(struct vxlan_dev *vxlan);
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
+
/* per-network namespace private data for this module */
struct vxlan_net {
struct list_head vxlan_list;
@@ -1065,6 +1067,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
synchronize_net();
+ vxlan_vs_del_dev(vxlan);
+
if (ipv4) {
udp_tunnel_sock_release(vxlan->vn4_sock->sock);
kfree(vxlan->vn4_sock);
@@ -2307,6 +2311,15 @@ static void vxlan_cleanup(unsigned long arg)
mod_timer(&vxlan->age_timer, next_timer);
}
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
+{
+ struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+
+ spin_lock(&vn->sock_lock);
+ hlist_del_init_rcu(&vxlan->hlist);
+ spin_unlock(&vn->sock_lock);
+}
+
static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
{
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
@@ -3099,12 +3112,6 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
static void vxlan_dellink(struct net_device *dev, struct list_head *head)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
-
- spin_lock(&vn->sock_lock);
- if (!hlist_unhashed(&vxlan->hlist))
- hlist_del_rcu(&vxlan->hlist);
- spin_unlock(&vn->sock_lock);
gro_cells_destroy(&vxlan->gro_cells);
list_del(&vxlan->next);
More information about the Devel
mailing list