From: Ben Pfaff Date: Thu, 29 Sep 2011 16:49:37 +0000 (-0700) Subject: datapath: Avoid use-after-free error in dp_device_event(). X-Git-Tag: v1.3.0~179 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=954fde3f2e68ba41f2f32faf5dbd900ce1b699a5;p=sliver-openvswitch.git datapath: Avoid use-after-free error in dp_device_event(). Commit f14d80834 "datapath: genl_notify() on port disappearances" frees the vport before passing it to ovs_vport_cmd_build_info(), which reads the freed data. Without this commit, the following commands consistently trigger a kernel BUG report on my test VM (which has slab debugging enabled) on 3 attempts: tunctl ovs-vsctl add-port br0 tap0 tunctl -d tap0 With this commit, I consistently don't see the BUG, on a few hundred tries in a tight loop. The interesting log information is: device tap0 entered promiscuous mode device tap0 left promiscuous mode BUG: unable to handle kernel paging request at 6b6b6ba7 IP: [] get_vport_protected+0x8/0x52 [openvswitch_mod] *pde = 00000000 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/pci0000:00/0000:00:04.0/net/eth1/carrier Modules linked in: brcompat_mod openvswitch_mod Pid: 653, comm: tunctl Not tainted 2.6.37+ #25 /Bochs EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at get_vport_protected+0x8/0x52 [openvswitch_mod] EAX: 6b6b6ba7 EBX: 00000000 ECX: 00000000 EDX: 00000000 ESI: c6d98400 EDI: c5c32074 EBP: c6ff1de8 ESP: c6ff1de4 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process tunctl (pid: 653, ti=c6ff0000 task=c5c3a820 task.ti=c6ff0000) Stack: 00000000 c6ff1df8 c8826b1d 6b6b6b6b c6d77ab0 c6ff1e14 c8826dc6 c7489160 00000f40 c6d98400 c6d77ab0 00000000 c6ff1e3c c88286fa 00000000 00000000 00000002 02ff1e34 00000000 c6d77ab0 c6df98a0 00000006 c6ff1e54 c8828aa2 Call Trace: [] ? get_dpifindex+0x1b/0x31 [openvswitch_mod] [] ? ovs_vport_cmd_fill_info+0x40/0x183 [openvswitch_mod] [] ? ovs_vport_cmd_build_info+0x3f/0x62 [openvswitch_mod] [] ? dp_device_event+0x56/0xb0 [openvswitch_mod] [] ? notifier_call_chain+0x6d/0x96 [] ? raw_notifier_call_chain+0xc/0xe [] ? call_netdevice_notifiers+0x3c/0x43 [] ? rollback_registered_many+0xd4/0x18b [] ? rollback_registered+0x23/0x28 [] ? unregister_netdevice_queue+0x4e/0x6b [] ? tun_chr_close+0x3f/0x76 Signed-off-by: Ben Pfaff Acked-by: Jesse Gross --- diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c index 942d628cb..07fd222de 100644 --- a/datapath/dp_notify.c +++ b/datapath/dp_notify.c @@ -37,9 +37,9 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event, if (!is_internal_dev(dev)) { struct sk_buff *reply; - dp_detach_port(vport); reply = ovs_vport_cmd_build_info(vport, 0, 0, OVS_VPORT_CMD_DEL); + dp_detach_port(vport); if (IS_ERR(reply)) { netlink_set_err(INIT_NET_GENL_SOCK, 0, dp_vport_multicast_group.id,