Skip to content

Commit 037f9cd

Browse files
TaeheeYoodavem330
authored andcommitted
net: rmnet: use upper/lower device infrastructure
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]>
1 parent 1dc49e9 commit 037f9cd

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
@@ -61,9 +61,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
6161

6262
kfree(port);
6363

64-
/* release reference on real_dev */
65-
dev_put(real_dev);
66-
6764
netdev_dbg(real_dev, "Removed from rmnet\n");
6865
return 0;
6966
}
@@ -89,9 +86,6 @@ static int rmnet_register_real_device(struct net_device *real_dev)
8986
return -EBUSY;
9087
}
9188

92-
/* hold on to real dev for MAP data */
93-
dev_hold(real_dev);
94-
9589
for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
9690
INIT_HLIST_HEAD(&port->muxed_ep[entry]);
9791

@@ -162,6 +156,10 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
162156
if (err)
163157
goto err1;
164158

159+
err = netdev_upper_dev_link(real_dev, dev, extack);
160+
if (err < 0)
161+
goto err2;
162+
165163
port->rmnet_mode = mode;
166164

167165
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
@@ -178,6 +176,8 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
178176

179177
return 0;
180178

179+
err2:
180+
unregister_netdevice(dev);
181181
err1:
182182
rmnet_unregister_real_device(real_dev, port);
183183
err0:
@@ -209,33 +209,30 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
209209
rmnet_vnd_dellink(mux_id, port, ep);
210210
kfree(ep);
211211
}
212+
netdev_upper_dev_unlink(real_dev, dev);
212213
rmnet_unregister_real_device(real_dev, port);
213214

214215
unregister_netdevice_queue(dev, head);
215216
}
216217

217-
static void rmnet_force_unassociate_device(struct net_device *dev)
218+
static void rmnet_force_unassociate_device(struct net_device *real_dev)
218219
{
219-
struct net_device *real_dev = dev;
220220
struct hlist_node *tmp_ep;
221221
struct rmnet_endpoint *ep;
222222
struct rmnet_port *port;
223223
unsigned long bkt_ep;
224224
LIST_HEAD(list);
225225

226-
if (!rmnet_is_real_dev_registered(real_dev))
227-
return;
228-
229226
ASSERT_RTNL();
230227

231-
port = rmnet_get_port_rtnl(dev);
228+
port = rmnet_get_port_rtnl(real_dev);
232229

233-
rmnet_unregister_bridge(dev, port);
230+
rmnet_unregister_bridge(real_dev, port);
234231

235232
hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
233+
netdev_upper_dev_unlink(real_dev, ep->egress_dev);
236234
unregister_netdevice_queue(ep->egress_dev, &list);
237235
rmnet_vnd_dellink(ep->mux_id, port, ep);
238-
239236
hlist_del_init_rcu(&ep->hlnode);
240237
kfree(ep);
241238
}
@@ -248,15 +245,15 @@ static void rmnet_force_unassociate_device(struct net_device *dev)
248245
static int rmnet_config_notify_cb(struct notifier_block *nb,
249246
unsigned long event, void *data)
250247
{
251-
struct net_device *dev = netdev_notifier_info_to_dev(data);
248+
struct net_device *real_dev = netdev_notifier_info_to_dev(data);
252249

253-
if (!dev)
250+
if (!rmnet_is_real_dev_registered(real_dev))
254251
return NOTIFY_DONE;
255252

256253
switch (event) {
257254
case NETDEV_UNREGISTER:
258-
netdev_dbg(dev, "Kernel unregister\n");
259-
rmnet_force_unassociate_device(dev);
255+
netdev_dbg(real_dev, "Kernel unregister\n");
256+
rmnet_force_unassociate_device(real_dev);
260257
break;
261258

262259
default:
@@ -477,8 +474,8 @@ static int __init rmnet_init(void)
477474

478475
static void __exit rmnet_exit(void)
479476
{
480-
unregister_netdevice_notifier(&rmnet_dev_notifier);
481477
rtnl_link_unregister(&rmnet_link_ops);
478+
unregister_netdevice_notifier(&rmnet_dev_notifier);
482479
}
483480

484481
module_init(rmnet_init)

0 commit comments

Comments
 (0)