]>
Commit | Line | Data |
---|---|---|
a15a8890 SL |
1 | From b7acd5b9344e6997587f2853406d9ff96716758f Mon Sep 17 00:00:00 2001 |
2 | From: Taehee Yoo <ap420073@gmail.com> | |
3 | Date: Sun, 9 Jun 2019 23:26:21 +0900 | |
4 | Subject: net: openvswitch: do not free vport if register_netdevice() is | |
5 | failed. | |
6 | ||
7 | [ Upstream commit 309b66970ee2abf721ecd0876a48940fa0b99a35 ] | |
8 | ||
9 | In order to create an internal vport, internal_dev_create() is used and | |
10 | that calls register_netdevice() internally. | |
11 | If register_netdevice() fails, it calls dev->priv_destructor() to free | |
12 | private data of netdev. actually, a private data of this is a vport. | |
13 | ||
14 | Hence internal_dev_create() should not free and use a vport after failure | |
15 | of register_netdevice(). | |
16 | ||
17 | Test command | |
18 | ovs-dpctl add-dp bonding_masters | |
19 | ||
20 | Splat looks like: | |
21 | [ 1035.667767] kasan: GPF could be caused by NULL-ptr deref or user memory access | |
22 | [ 1035.675958] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI | |
23 | [ 1035.676916] CPU: 1 PID: 1028 Comm: ovs-vswitchd Tainted: G B 5.2.0-rc3+ #240 | |
24 | [ 1035.676916] RIP: 0010:internal_dev_create+0x2e5/0x4e0 [openvswitch] | |
25 | [ 1035.676916] Code: 48 c1 ea 03 80 3c 02 00 0f 85 9f 01 00 00 4c 8b 23 48 b8 00 00 00 00 00 fc ff df 49 8d bc 24 60 05 00 00 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 86 01 00 00 49 8b bc 24 60 05 00 00 e8 e4 68 f4 | |
26 | [ 1035.713720] RSP: 0018:ffff88810dcb7578 EFLAGS: 00010206 | |
27 | [ 1035.713720] RAX: dffffc0000000000 RBX: ffff88810d13fe08 RCX: ffffffff84297704 | |
28 | [ 1035.713720] RDX: 00000000000000ac RSI: 0000000000000000 RDI: 0000000000000560 | |
29 | [ 1035.713720] RBP: 00000000ffffffef R08: fffffbfff0d3b881 R09: fffffbfff0d3b881 | |
30 | [ 1035.713720] R10: 0000000000000001 R11: fffffbfff0d3b880 R12: 0000000000000000 | |
31 | [ 1035.768776] R13: 0000607ee460b900 R14: ffff88810dcb7690 R15: ffff88810dcb7698 | |
32 | [ 1035.777709] FS: 00007f02095fc980(0000) GS:ffff88811b400000(0000) knlGS:0000000000000000 | |
33 | [ 1035.777709] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | |
34 | [ 1035.777709] CR2: 00007ffdf01d2f28 CR3: 0000000108258000 CR4: 00000000001006e0 | |
35 | [ 1035.777709] Call Trace: | |
36 | [ 1035.777709] ovs_vport_add+0x267/0x4f0 [openvswitch] | |
37 | [ 1035.777709] new_vport+0x15/0x1e0 [openvswitch] | |
38 | [ 1035.777709] ovs_vport_cmd_new+0x567/0xd10 [openvswitch] | |
39 | [ 1035.777709] ? ovs_dp_cmd_dump+0x490/0x490 [openvswitch] | |
40 | [ 1035.777709] ? __kmalloc+0x131/0x2e0 | |
41 | [ 1035.777709] ? genl_family_rcv_msg+0xa54/0x1030 | |
42 | [ 1035.777709] genl_family_rcv_msg+0x63a/0x1030 | |
43 | [ 1035.777709] ? genl_unregister_family+0x630/0x630 | |
44 | [ 1035.841681] ? debug_show_all_locks+0x2d0/0x2d0 | |
45 | [ ... ] | |
46 | ||
47 | Fixes: cf124db566e6 ("net: Fix inconsistent teardown and release of private netdev state.") | |
48 | Signed-off-by: Taehee Yoo <ap420073@gmail.com> | |
49 | Reviewed-by: Greg Rose <gvrose8192@gmail.com> | |
50 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
51 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
52 | --- | |
53 | net/openvswitch/vport-internal_dev.c | 18 ++++++++++++------ | |
54 | 1 file changed, 12 insertions(+), 6 deletions(-) | |
55 | ||
56 | diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c | |
57 | index bb95c43aae76..5a304cfc8423 100644 | |
58 | --- a/net/openvswitch/vport-internal_dev.c | |
59 | +++ b/net/openvswitch/vport-internal_dev.c | |
60 | @@ -169,7 +169,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |
61 | { | |
62 | struct vport *vport; | |
63 | struct internal_dev *internal_dev; | |
64 | + struct net_device *dev; | |
65 | int err; | |
66 | + bool free_vport = true; | |
67 | ||
68 | vport = ovs_vport_alloc(0, &ovs_internal_vport_ops, parms); | |
69 | if (IS_ERR(vport)) { | |
70 | @@ -177,8 +179,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |
71 | goto error; | |
72 | } | |
73 | ||
74 | - vport->dev = alloc_netdev(sizeof(struct internal_dev), | |
75 | - parms->name, NET_NAME_USER, do_setup); | |
76 | + dev = alloc_netdev(sizeof(struct internal_dev), | |
77 | + parms->name, NET_NAME_USER, do_setup); | |
78 | + vport->dev = dev; | |
79 | if (!vport->dev) { | |
80 | err = -ENOMEM; | |
81 | goto error_free_vport; | |
82 | @@ -199,8 +202,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |
83 | ||
84 | rtnl_lock(); | |
85 | err = register_netdevice(vport->dev); | |
86 | - if (err) | |
87 | + if (err) { | |
88 | + free_vport = false; | |
89 | goto error_unlock; | |
90 | + } | |
91 | ||
92 | dev_set_promiscuity(vport->dev, 1); | |
93 | rtnl_unlock(); | |
94 | @@ -210,11 +215,12 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |
95 | ||
96 | error_unlock: | |
97 | rtnl_unlock(); | |
98 | - free_percpu(vport->dev->tstats); | |
99 | + free_percpu(dev->tstats); | |
100 | error_free_netdev: | |
101 | - free_netdev(vport->dev); | |
102 | + free_netdev(dev); | |
103 | error_free_vport: | |
104 | - ovs_vport_free(vport); | |
105 | + if (free_vport) | |
106 | + ovs_vport_free(vport); | |
107 | error: | |
108 | return ERR_PTR(err); | |
109 | } | |
110 | -- | |
111 | 2.20.1 | |
112 |