]>
Commit | Line | Data |
---|---|---|
122ccbab GKH |
1 | From foo@baz Thu 08 Aug 2019 08:50:40 AM CEST |
2 | From: Jiri Pirko <jiri@mellanox.com> | |
3 | Date: Sun, 28 Jul 2019 14:56:36 +0200 | |
4 | Subject: net: fix ifindex collision during namespace removal | |
5 | ||
6 | From: Jiri Pirko <jiri@mellanox.com> | |
7 | ||
8 | [ Upstream commit 55b40dbf0e76b4bfb9d8b3a16a0208640a9a45df ] | |
9 | ||
10 | Commit aca51397d014 ("netns: Fix arbitrary net_device-s corruptions | |
11 | on net_ns stop.") introduced a possibility to hit a BUG in case device | |
12 | is returning back to init_net and two following conditions are met: | |
13 | 1) dev->ifindex value is used in a name of another "dev%d" | |
14 | device in init_net. | |
15 | 2) dev->name is used by another device in init_net. | |
16 | ||
17 | Under real life circumstances this is hard to get. Therefore this has | |
18 | been present happily for over 10 years. To reproduce: | |
19 | ||
20 | $ ip a | |
21 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 | |
22 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 | |
23 | inet 127.0.0.1/8 scope host lo | |
24 | valid_lft forever preferred_lft forever | |
25 | inet6 ::1/128 scope host | |
26 | valid_lft forever preferred_lft forever | |
27 | 2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
28 | link/ether 86:89:3f:86:61:29 brd ff:ff:ff:ff:ff:ff | |
29 | 3: enp0s2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
30 | link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff | |
31 | $ ip netns add ns1 | |
32 | $ ip -n ns1 link add dummy1ns1 type dummy | |
33 | $ ip -n ns1 link add dummy2ns1 type dummy | |
34 | $ ip link set enp0s2 netns ns1 | |
35 | $ ip -n ns1 link set enp0s2 name dummy0 | |
36 | [ 100.858894] virtio_net virtio0 dummy0: renamed from enp0s2 | |
37 | $ ip link add dev4 type dummy | |
38 | $ ip -n ns1 a | |
39 | 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 | |
40 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 | |
41 | 2: dummy1ns1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
42 | link/ether 16:63:4c:38:3e:ff brd ff:ff:ff:ff:ff:ff | |
43 | 3: dummy2ns1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
44 | link/ether aa:9e:86:dd:6b:5d brd ff:ff:ff:ff:ff:ff | |
45 | 4: dummy0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
46 | link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff | |
47 | $ ip a | |
48 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 | |
49 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 | |
50 | inet 127.0.0.1/8 scope host lo | |
51 | valid_lft forever preferred_lft forever | |
52 | inet6 ::1/128 scope host | |
53 | valid_lft forever preferred_lft forever | |
54 | 2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
55 | link/ether 86:89:3f:86:61:29 brd ff:ff:ff:ff:ff:ff | |
56 | 4: dev4: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 | |
57 | link/ether 5a:e1:4a:b6:ec:f8 brd ff:ff:ff:ff:ff:ff | |
58 | $ ip netns del ns1 | |
59 | [ 158.717795] default_device_exit: failed to move dummy0 to init_net: -17 | |
60 | [ 158.719316] ------------[ cut here ]------------ | |
61 | [ 158.720591] kernel BUG at net/core/dev.c:9824! | |
62 | [ 158.722260] invalid opcode: 0000 [#1] SMP KASAN PTI | |
63 | [ 158.723728] CPU: 0 PID: 56 Comm: kworker/u2:1 Not tainted 5.3.0-rc1+ #18 | |
64 | [ 158.725422] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014 | |
65 | [ 158.727508] Workqueue: netns cleanup_net | |
66 | [ 158.728915] RIP: 0010:default_device_exit.cold+0x1d/0x1f | |
67 | [ 158.730683] Code: 84 e8 18 c9 3e fe 0f 0b e9 70 90 ff ff e8 36 e4 52 fe 89 d9 4c 89 e2 48 c7 c6 80 d6 25 84 48 c7 c7 20 c0 25 84 e8 f4 c8 3e | |
68 | [ 158.736854] RSP: 0018:ffff8880347e7b90 EFLAGS: 00010282 | |
69 | [ 158.738752] RAX: 000000000000003b RBX: 00000000ffffffef RCX: 0000000000000000 | |
70 | [ 158.741369] RDX: 0000000000000000 RSI: ffffffff8128013d RDI: ffffed10068fcf64 | |
71 | [ 158.743418] RBP: ffff888033550170 R08: 000000000000003b R09: fffffbfff0b94b9c | |
72 | [ 158.745626] R10: fffffbfff0b94b9b R11: ffffffff85ca5cdf R12: ffff888032f28000 | |
73 | [ 158.748405] R13: dffffc0000000000 R14: ffff8880335501b8 R15: 1ffff110068fcf72 | |
74 | [ 158.750638] FS: 0000000000000000(0000) GS:ffff888036000000(0000) knlGS:0000000000000000 | |
75 | [ 158.752944] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | |
76 | [ 158.755245] CR2: 00007fe8b45d21d0 CR3: 00000000340b4005 CR4: 0000000000360ef0 | |
77 | [ 158.757654] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 | |
78 | [ 158.760012] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 | |
79 | [ 158.762758] Call Trace: | |
80 | [ 158.763882] ? dev_change_net_namespace+0xbb0/0xbb0 | |
81 | [ 158.766148] ? devlink_nl_cmd_set_doit+0x520/0x520 | |
82 | [ 158.768034] ? dev_change_net_namespace+0xbb0/0xbb0 | |
83 | [ 158.769870] ops_exit_list.isra.0+0xa8/0x150 | |
84 | [ 158.771544] cleanup_net+0x446/0x8f0 | |
85 | [ 158.772945] ? unregister_pernet_operations+0x4a0/0x4a0 | |
86 | [ 158.775294] process_one_work+0xa1a/0x1740 | |
87 | [ 158.776896] ? pwq_dec_nr_in_flight+0x310/0x310 | |
88 | [ 158.779143] ? do_raw_spin_lock+0x11b/0x280 | |
89 | [ 158.780848] worker_thread+0x9e/0x1060 | |
90 | [ 158.782500] ? process_one_work+0x1740/0x1740 | |
91 | [ 158.784454] kthread+0x31b/0x420 | |
92 | [ 158.786082] ? __kthread_create_on_node+0x3f0/0x3f0 | |
93 | [ 158.788286] ret_from_fork+0x3a/0x50 | |
94 | [ 158.789871] ---[ end trace defd6c657c71f936 ]--- | |
95 | [ 158.792273] RIP: 0010:default_device_exit.cold+0x1d/0x1f | |
96 | [ 158.795478] Code: 84 e8 18 c9 3e fe 0f 0b e9 70 90 ff ff e8 36 e4 52 fe 89 d9 4c 89 e2 48 c7 c6 80 d6 25 84 48 c7 c7 20 c0 25 84 e8 f4 c8 3e | |
97 | [ 158.804854] RSP: 0018:ffff8880347e7b90 EFLAGS: 00010282 | |
98 | [ 158.807865] RAX: 000000000000003b RBX: 00000000ffffffef RCX: 0000000000000000 | |
99 | [ 158.811794] RDX: 0000000000000000 RSI: ffffffff8128013d RDI: ffffed10068fcf64 | |
100 | [ 158.816652] RBP: ffff888033550170 R08: 000000000000003b R09: fffffbfff0b94b9c | |
101 | [ 158.820930] R10: fffffbfff0b94b9b R11: ffffffff85ca5cdf R12: ffff888032f28000 | |
102 | [ 158.825113] R13: dffffc0000000000 R14: ffff8880335501b8 R15: 1ffff110068fcf72 | |
103 | [ 158.829899] FS: 0000000000000000(0000) GS:ffff888036000000(0000) knlGS:0000000000000000 | |
104 | [ 158.834923] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | |
105 | [ 158.838164] CR2: 00007fe8b45d21d0 CR3: 00000000340b4005 CR4: 0000000000360ef0 | |
106 | [ 158.841917] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 | |
107 | [ 158.845149] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 | |
108 | ||
109 | Fix this by checking if a device with the same name exists in init_net | |
110 | and fallback to original code - dev%d to allocate name - in case it does. | |
111 | ||
112 | This was found using syzkaller. | |
113 | ||
114 | Fixes: aca51397d014 ("netns: Fix arbitrary net_device-s corruptions on net_ns stop.") | |
115 | Signed-off-by: Jiri Pirko <jiri@mellanox.com> | |
116 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
117 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
118 | --- | |
119 | net/core/dev.c | 2 ++ | |
120 | 1 file changed, 2 insertions(+) | |
121 | ||
122 | --- a/net/core/dev.c | |
123 | +++ b/net/core/dev.c | |
124 | @@ -9510,6 +9510,8 @@ static void __net_exit default_device_ex | |
125 | ||
126 | /* Push remaining network devices to init_net */ | |
127 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); | |
128 | + if (__dev_get_by_name(&init_net, fb_name)) | |
129 | + snprintf(fb_name, IFNAMSIZ, "dev%%d"); | |
130 | err = dev_change_net_namespace(dev, &init_net, fb_name); | |
131 | if (err) { | |
132 | pr_emerg("%s: failed to move %s to init_net: %d\n", |