Skip to content

Commit 7997816

Browse files
TaeheeYoogregkh
authored andcommitted
net: rmnet: use upper/lower device infrastructure
[ Upstream commit 037f9cd ] netdev_upper_dev_link() is useful to manage lower/upper interfaces. And this function internally validates looping, maximum depth. All or most virtual interfaces that could have a real interface (e.g. macsec, macvlan, ipvlan etc.) use lower/upper infrastructure. Test commands: modprobe rmnet ip link add dummy0 type dummy ip link add rmnet1 link dummy0 type rmnet mux_id 1 for i in {2..100} do let A=$i-1 ip link add rmnet$i link rmnet$A type rmnet mux_id $i done ip link del dummy0 The purpose of the test commands is to make stack overflow. Splat looks like: [ 52.411438][ T1395] BUG: KASAN: slab-out-of-bounds in find_busiest_group+0x27e/0x2c00 [ 52.413218][ T1395] Write of size 64 at addr ffff8880c774bde0 by task ip/1395 [ 52.414841][ T1395] [ 52.430720][ T1395] CPU: 1 PID: 1395 Comm: ip Not tainted 5.6.0-rc1+ #447 [ 52.496511][ T1395] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 52.513597][ T1395] Call Trace: [ 52.546516][ T1395] [ 52.558773][ T1395] Allocated by task 3171537984: [ 52.588290][ T1395] BUG: unable to handle page fault for address: ffffffffb999e260 [ 52.589311][ T1395] #PF: supervisor read access in kernel mode [ 52.590529][ T1395] #PF: error_code(0x0000) - not-present page [ 52.591374][ T1395] PGD d6818067 P4D d6818067 PUD d6819063 PMD 0 [ 52.592288][ T1395] Thread overran stack, or stack corrupted [ 52.604980][ T1395] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI [ 52.605856][ T1395] CPU: 1 PID: 1395 Comm: ip Not tainted 5.6.0-rc1+ #447 [ 52.611764][ T1395] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 52.621520][ T1395] RIP: 0010:stack_depot_fetch+0x10/0x30 [ 52.622296][ T1395] Code: ff e9 f9 fe ff ff 48 89 df e8 9c 1d 91 ff e9 ca fe ff ff cc cc cc cc cc cc cc 89 f8 0 [ 52.627887][ T1395] RSP: 0018:ffff8880c774bb60 EFLAGS: 00010006 [ 52.628735][ T1395] RAX: 00000000001f8880 RBX: ffff8880c774d140 RCX: 0000000000000000 [ 52.631773][ T1395] RDX: 000000000000001d RSI: ffff8880c774bb68 RDI: 0000000000003ff0 [ 52.649584][ T1395] RBP: ffffea00031dd200 R08: ffffed101b43e403 R09: ffffed101b43e403 [ 52.674857][ T1395] R10: 0000000000000001 R11: ffffed101b43e402 R12: ffff8880d900e5c0 [ 52.678257][ T1395] R13: ffff8880c774c000 R14: 0000000000000000 R15: dffffc0000000000 [ 52.694541][ T1395] FS: 00007fe867f6e0c0(0000) GS:ffff8880da000000(0000) knlGS:0000000000000000 [ 52.764039][ T1395] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 52.815008][ T1395] CR2: ffffffffb999e260 CR3: 00000000c26aa005 CR4: 00000000000606e0 [ 52.862312][ T1395] Call Trace: [ 52.887133][ T1395] Modules linked in: dummy rmnet veth openvswitch nsh nf_conncount nf_nat nf_conntrack nf_dex [ 52.936749][ T1395] CR2: ffffffffb999e260 [ 52.965695][ T1395] ---[ end trace 7e32ca99482dbb31 ]--- [ 52.966556][ T1395] RIP: 0010:stack_depot_fetch+0x10/0x30 [ 52.971083][ T1395] Code: ff e9 f9 fe ff ff 48 89 df e8 9c 1d 91 ff e9 ca fe ff ff cc cc cc cc cc cc cc 89 f8 0 [ 53.003650][ T1395] RSP: 0018:ffff8880c774bb60 EFLAGS: 00010006 [ 53.043183][ T1395] RAX: 00000000001f8880 RBX: ffff8880c774d140 RCX: 0000000000000000 [ 53.076480][ T1395] RDX: 000000000000001d RSI: ffff8880c774bb68 RDI: 0000000000003ff0 [ 53.093858][ T1395] RBP: ffffea00031dd200 R08: ffffed101b43e403 R09: ffffed101b43e403 [ 53.112795][ T1395] R10: 0000000000000001 R11: ffffed101b43e402 R12: ffff8880d900e5c0 [ 53.139837][ T1395] R13: ffff8880c774c000 R14: 0000000000000000 R15: dffffc0000000000 [ 53.141500][ T1395] FS: 00007fe867f6e0c0(0000) GS:ffff8880da000000(0000) knlGS:0000000000000000 [ 53.143343][ T1395] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 53.152007][ T1395] CR2: ffffffffb999e260 CR3: 00000000c26aa005 CR4: 00000000000606e0 [ 53.156459][ T1395] Kernel panic - not syncing: Fatal exception [ 54.213570][ T1395] Shutting down cpus with NMI [ 54.354112][ T1395] Kernel Offset: 0x33000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0x) [ 54.355687][ T1395] Rebooting in 5 seconds.. Fixes: b37f78f ("net: qualcomm: rmnet: Fix crash on real dev unregistration") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 48c5bfb commit 7997816

File tree

1 file changed

+16
-19
lines changed

1 file changed

+16
-19
lines changed

drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
7070

7171
kfree(port);
7272

73-
/* release reference on real_dev */
74-
dev_put(real_dev);
75-
7673
netdev_dbg(real_dev, "Removed from rmnet\n");
7774
return 0;
7875
}
@@ -98,9 +95,6 @@ static int rmnet_register_real_device(struct net_device *real_dev)
9895
return -EBUSY;
9996
}
10097

101-
/* hold on to real dev for MAP data */
102-
dev_hold(real_dev);
103-
10498
for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
10599
INIT_HLIST_HEAD(&port->muxed_ep[entry]);
106100

@@ -171,6 +165,10 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
171165
if (err)
172166
goto err1;
173167

168+
err = netdev_upper_dev_link(real_dev, dev, extack);
169+
if (err < 0)
170+
goto err2;
171+
174172
port->rmnet_mode = mode;
175173

176174
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
@@ -187,6 +185,8 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
187185

188186
return 0;
189187

188+
err2:
189+
unregister_netdevice(dev);
190190
err1:
191191
rmnet_unregister_real_device(real_dev, port);
192192
err0:
@@ -218,33 +218,30 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
218218
rmnet_vnd_dellink(mux_id, port, ep);
219219
kfree(ep);
220220
}
221+
netdev_upper_dev_unlink(real_dev, dev);
221222
rmnet_unregister_real_device(real_dev, port);
222223

223224
unregister_netdevice_queue(dev, head);
224225
}
225226

226-
static void rmnet_force_unassociate_device(struct net_device *dev)
227+
static void rmnet_force_unassociate_device(struct net_device *real_dev)
227228
{
228-
struct net_device *real_dev = dev;
229229
struct hlist_node *tmp_ep;
230230
struct rmnet_endpoint *ep;
231231
struct rmnet_port *port;
232232
unsigned long bkt_ep;
233233
LIST_HEAD(list);
234234

235-
if (!rmnet_is_real_dev_registered(real_dev))
236-
return;
237-
238235
ASSERT_RTNL();
239236

240-
port = rmnet_get_port_rtnl(dev);
237+
port = rmnet_get_port_rtnl(real_dev);
241238

242-
rmnet_unregister_bridge(dev, port);
239+
rmnet_unregister_bridge(real_dev, port);
243240

244241
hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
242+
netdev_upper_dev_unlink(real_dev, ep->egress_dev);
245243
unregister_netdevice_queue(ep->egress_dev, &list);
246244
rmnet_vnd_dellink(ep->mux_id, port, ep);
247-
248245
hlist_del_init_rcu(&ep->hlnode);
249246
kfree(ep);
250247
}
@@ -257,15 +254,15 @@ static void rmnet_force_unassociate_device(struct net_device *dev)
257254
static int rmnet_config_notify_cb(struct notifier_block *nb,
258255
unsigned long event, void *data)
259256
{
260-
struct net_device *dev = netdev_notifier_info_to_dev(data);
257+
struct net_device *real_dev = netdev_notifier_info_to_dev(data);
261258

262-
if (!dev)
259+
if (!rmnet_is_real_dev_registered(real_dev))
263260
return NOTIFY_DONE;
264261

265262
switch (event) {
266263
case NETDEV_UNREGISTER:
267-
netdev_dbg(dev, "Kernel unregister\n");
268-
rmnet_force_unassociate_device(dev);
264+
netdev_dbg(real_dev, "Kernel unregister\n");
265+
rmnet_force_unassociate_device(real_dev);
269266
break;
270267

271268
default:
@@ -486,8 +483,8 @@ static int __init rmnet_init(void)
486483

487484
static void __exit rmnet_exit(void)
488485
{
489-
unregister_netdevice_notifier(&rmnet_dev_notifier);
490486
rtnl_link_unregister(&rmnet_link_ops);
487+
unregister_netdevice_notifier(&rmnet_dev_notifier);
491488
}
492489

493490
module_init(rmnet_init)

0 commit comments

Comments
 (0)