Skip to content

Commit 795c03a

Browse files
committed
Merge branch 'net-rmnet-fix-several-bugs'
Taehee Yoo says: ==================== net: rmnet: fix several bugs This patchset is to fix several bugs in RMNET module. 1. The first patch fixes NULL-ptr-deref in rmnet_newlink(). When rmnet interface is being created, it uses IFLA_LINK without checking NULL. So, if userspace doesn't set IFLA_LINK, panic will occur. In this patch, checking NULL pointer code is added. 2. The second patch fixes NULL-ptr-deref in rmnet_changelink(). To get real device in rmnet_changelink(), it uses IFLA_LINK. But, IFLA_LINK should not be used in rmnet_changelink(). 3. The third patch fixes suspicious RCU usage in rmnet_get_port(). rmnet_get_port() uses rcu_dereference_rtnl(). But, rmnet_get_port() is used by datapath. So, rcu_dereference_bh() should be used instead of rcu_dereference_rtnl(). 4. The fourth patch fixes suspicious RCU usage in rmnet_force_unassociate_device(). RCU critical section should not be scheduled. But, unregister_netdevice_queue() in the rmnet_force_unassociate_device() would be scheduled. So, the RCU warning occurs. In this patch, the rcu_read_lock() in the rmnet_force_unassociate_device() is removed because it's unnecessary. 5. The fifth patch fixes duplicate MUX ID case. RMNET MUX ID is unique. So, rmnet interface isn't allowed to be created, which have a duplicate MUX ID. But, only rmnet_newlink() checks this condition, rmnet_changelink() doesn't check this. So, duplicate MUX ID case would happen. 6. The sixth patch fixes upper/lower interface relationship problems. When IFLA_LINK is used, the upper/lower infrastructure should be used. Because it checks the maximum depth of upper/lower interfaces and it also checks circular interface relationship, etc. In this patch, netdev_upper_dev_link() is used. 7. The seventh patch fixes bridge related problems. a) ->ndo_del_slave() doesn't work. b) It couldn't detect circular upper/lower interface relationship. c) It couldn't prevent stack overflow because of too deep depth of upper/lower interface d) It doesn't check the number of lower interfaces. e) Panics because of several reasons. These problems are actually the same problem. So, this patch fixes these problems. 8. The eighth patch fixes packet forwarding issue in bridge mode Packet forwarding is not working in rmnet bridge mode. Because when a packet is forwarded, skb_push() for an ethernet header is needed. But it doesn't call skb_push(). So, the ethernet header will be lost. Change log: - update commit logs. - drop two patches in this patchset because of wrong target branch. - ("net: rmnet: add missing module alias") - ("net: rmnet: print error message when command fails") - remove unneessary rcu_read_lock() in the third patch. - use rcu_dereference_bh() instead of rcu_dereference in third patch. - do not allow to add a bridge device if rmnet interface is already bridge mode in the seventh patch. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b82cf17 + ad3cc31 commit 795c03a

File tree

5 files changed

+98
-107
lines changed

5 files changed

+98
-107
lines changed

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

Lines changed: 91 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,6 @@
1313
#include "rmnet_vnd.h"
1414
#include "rmnet_private.h"
1515

16-
/* Locking scheme -
17-
* The shared resource which needs to be protected is realdev->rx_handler_data.
18-
* For the writer path, this is using rtnl_lock(). The writer paths are
19-
* rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These
20-
* paths are already called with rtnl_lock() acquired in. There is also an
21-
* ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For
22-
* dereference here, we will need to use rtnl_dereference(). Dev list writing
23-
* needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link().
24-
* For the reader path, the real_dev->rx_handler_data is called in the TX / RX
25-
* path. We only need rcu_read_lock() for these scenarios. In these cases,
26-
* the rcu_read_lock() is held in __dev_queue_xmit() and
27-
* netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl()
28-
* to get the relevant information. For dev list reading, we again acquire
29-
* rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu().
30-
* We also use unregister_netdevice_many() to free all rmnet devices in
31-
* rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in
32-
* same context.
33-
*/
34-
3516
/* Local Definitions and Declarations */
3617

3718
static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = {
@@ -51,19 +32,17 @@ rmnet_get_port_rtnl(const struct net_device *real_dev)
5132
return rtnl_dereference(real_dev->rx_handler_data);
5233
}
5334

54-
static int rmnet_unregister_real_device(struct net_device *real_dev,
55-
struct rmnet_port *port)
35+
static int rmnet_unregister_real_device(struct net_device *real_dev)
5636
{
37+
struct rmnet_port *port = rmnet_get_port_rtnl(real_dev);
38+
5739
if (port->nr_rmnet_devs)
5840
return -EINVAL;
5941

6042
netdev_rx_handler_unregister(real_dev);
6143

6244
kfree(port);
6345

64-
/* release reference on real_dev */
65-
dev_put(real_dev);
66-
6746
netdev_dbg(real_dev, "Removed from rmnet\n");
6847
return 0;
6948
}
@@ -89,38 +68,40 @@ static int rmnet_register_real_device(struct net_device *real_dev)
8968
return -EBUSY;
9069
}
9170

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

9874
netdev_dbg(real_dev, "registered with rmnet\n");
9975
return 0;
10076
}
10177

102-
static void rmnet_unregister_bridge(struct net_device *dev,
103-
struct rmnet_port *port)
78+
static void rmnet_unregister_bridge(struct rmnet_port *port)
10479
{
105-
struct rmnet_port *bridge_port;
106-
struct net_device *bridge_dev;
80+
struct net_device *bridge_dev, *real_dev, *rmnet_dev;
81+
struct rmnet_port *real_port;
10782

10883
if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
10984
return;
11085

111-
/* bridge slave handling */
86+
rmnet_dev = port->rmnet_dev;
11287
if (!port->nr_rmnet_devs) {
113-
bridge_dev = port->bridge_ep;
88+
/* bridge device */
89+
real_dev = port->bridge_ep;
90+
bridge_dev = port->dev;
11491

115-
bridge_port = rmnet_get_port_rtnl(bridge_dev);
116-
bridge_port->bridge_ep = NULL;
117-
bridge_port->rmnet_mode = RMNET_EPMODE_VND;
92+
real_port = rmnet_get_port_rtnl(real_dev);
93+
real_port->bridge_ep = NULL;
94+
real_port->rmnet_mode = RMNET_EPMODE_VND;
11895
} else {
96+
/* real device */
11997
bridge_dev = port->bridge_ep;
12098

121-
bridge_port = rmnet_get_port_rtnl(bridge_dev);
122-
rmnet_unregister_real_device(bridge_dev, bridge_port);
99+
port->bridge_ep = NULL;
100+
port->rmnet_mode = RMNET_EPMODE_VND;
123101
}
102+
103+
netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
104+
rmnet_unregister_real_device(bridge_dev);
124105
}
125106

126107
static int rmnet_newlink(struct net *src_net, struct net_device *dev,
@@ -135,6 +116,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
135116
int err = 0;
136117
u16 mux_id;
137118

119+
if (!tb[IFLA_LINK]) {
120+
NL_SET_ERR_MSG_MOD(extack, "link not specified");
121+
return -EINVAL;
122+
}
123+
138124
real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
139125
if (!real_dev || !dev)
140126
return -ENODEV;
@@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
157143
if (err)
158144
goto err1;
159145

146+
err = netdev_upper_dev_link(real_dev, dev, extack);
147+
if (err < 0)
148+
goto err2;
149+
160150
port->rmnet_mode = mode;
151+
port->rmnet_dev = dev;
161152

162153
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
163154

@@ -173,8 +164,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
173164

174165
return 0;
175166

167+
err2:
168+
unregister_netdevice(dev);
169+
rmnet_vnd_dellink(mux_id, port, ep);
176170
err1:
177-
rmnet_unregister_real_device(real_dev, port);
171+
rmnet_unregister_real_device(real_dev);
178172
err0:
179173
kfree(ep);
180174
return err;
@@ -183,77 +177,74 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
183177
static void rmnet_dellink(struct net_device *dev, struct list_head *head)
184178
{
185179
struct rmnet_priv *priv = netdev_priv(dev);
186-
struct net_device *real_dev;
180+
struct net_device *real_dev, *bridge_dev;
181+
struct rmnet_port *real_port, *bridge_port;
187182
struct rmnet_endpoint *ep;
188-
struct rmnet_port *port;
189-
u8 mux_id;
183+
u8 mux_id = priv->mux_id;
190184

191185
real_dev = priv->real_dev;
192186

193-
if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
187+
if (!rmnet_is_real_dev_registered(real_dev))
194188
return;
195189

196-
port = rmnet_get_port_rtnl(real_dev);
197-
198-
mux_id = rmnet_vnd_get_mux(dev);
190+
real_port = rmnet_get_port_rtnl(real_dev);
191+
bridge_dev = real_port->bridge_ep;
192+
if (bridge_dev) {
193+
bridge_port = rmnet_get_port_rtnl(bridge_dev);
194+
rmnet_unregister_bridge(bridge_port);
195+
}
199196

200-
ep = rmnet_get_endpoint(port, mux_id);
197+
ep = rmnet_get_endpoint(real_port, mux_id);
201198
if (ep) {
202199
hlist_del_init_rcu(&ep->hlnode);
203-
rmnet_unregister_bridge(dev, port);
204-
rmnet_vnd_dellink(mux_id, port, ep);
200+
rmnet_vnd_dellink(mux_id, real_port, ep);
205201
kfree(ep);
206202
}
207-
rmnet_unregister_real_device(real_dev, port);
208203

204+
netdev_upper_dev_unlink(real_dev, dev);
205+
rmnet_unregister_real_device(real_dev);
209206
unregister_netdevice_queue(dev, head);
210207
}
211208

212-
static void rmnet_force_unassociate_device(struct net_device *dev)
209+
static void rmnet_force_unassociate_device(struct net_device *real_dev)
213210
{
214-
struct net_device *real_dev = dev;
215211
struct hlist_node *tmp_ep;
216212
struct rmnet_endpoint *ep;
217213
struct rmnet_port *port;
218214
unsigned long bkt_ep;
219215
LIST_HEAD(list);
220216

221-
if (!rmnet_is_real_dev_registered(real_dev))
222-
return;
223-
224-
ASSERT_RTNL();
225-
226-
port = rmnet_get_port_rtnl(dev);
227-
228-
rcu_read_lock();
229-
rmnet_unregister_bridge(dev, port);
230-
231-
hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
232-
unregister_netdevice_queue(ep->egress_dev, &list);
233-
rmnet_vnd_dellink(ep->mux_id, port, ep);
217+
port = rmnet_get_port_rtnl(real_dev);
234218

235-
hlist_del_init_rcu(&ep->hlnode);
236-
kfree(ep);
219+
if (port->nr_rmnet_devs) {
220+
/* real device */
221+
rmnet_unregister_bridge(port);
222+
hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
223+
unregister_netdevice_queue(ep->egress_dev, &list);
224+
netdev_upper_dev_unlink(real_dev, ep->egress_dev);
225+
rmnet_vnd_dellink(ep->mux_id, port, ep);
226+
hlist_del_init_rcu(&ep->hlnode);
227+
kfree(ep);
228+
}
229+
rmnet_unregister_real_device(real_dev);
230+
unregister_netdevice_many(&list);
231+
} else {
232+
rmnet_unregister_bridge(port);
237233
}
238-
239-
rcu_read_unlock();
240-
unregister_netdevice_many(&list);
241-
242-
rmnet_unregister_real_device(real_dev, port);
243234
}
244235

245236
static int rmnet_config_notify_cb(struct notifier_block *nb,
246237
unsigned long event, void *data)
247238
{
248-
struct net_device *dev = netdev_notifier_info_to_dev(data);
239+
struct net_device *real_dev = netdev_notifier_info_to_dev(data);
249240

250-
if (!dev)
241+
if (!rmnet_is_real_dev_registered(real_dev))
251242
return NOTIFY_DONE;
252243

253244
switch (event) {
254245
case NETDEV_UNREGISTER:
255-
netdev_dbg(dev, "Kernel unregister\n");
256-
rmnet_force_unassociate_device(dev);
246+
netdev_dbg(real_dev, "Kernel unregister\n");
247+
rmnet_force_unassociate_device(real_dev);
257248
break;
258249

259250
default:
@@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
295286
if (!dev)
296287
return -ENODEV;
297288

298-
real_dev = __dev_get_by_index(dev_net(dev),
299-
nla_get_u32(tb[IFLA_LINK]));
300-
301-
if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
289+
real_dev = priv->real_dev;
290+
if (!rmnet_is_real_dev_registered(real_dev))
302291
return -ENODEV;
303292

304293
port = rmnet_get_port_rtnl(real_dev);
305294

306295
if (data[IFLA_RMNET_MUX_ID]) {
307296
mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
297+
if (rmnet_get_endpoint(port, mux_id)) {
298+
NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
299+
return -EINVAL;
300+
}
308301
ep = rmnet_get_endpoint(port, priv->mux_id);
309302
if (!ep)
310303
return -ENODEV;
@@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
379372
.fill_info = rmnet_fill_info,
380373
};
381374

382-
/* Needs either rcu_read_lock() or rtnl lock */
383-
struct rmnet_port *rmnet_get_port(struct net_device *real_dev)
375+
struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev)
384376
{
385377
if (rmnet_is_real_dev_registered(real_dev))
386-
return rcu_dereference_rtnl(real_dev->rx_handler_data);
378+
return rcu_dereference_bh(real_dev->rx_handler_data);
387379
else
388380
return NULL;
389381
}
@@ -409,24 +401,35 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
409401
struct rmnet_port *port, *slave_port;
410402
int err;
411403

412-
port = rmnet_get_port(real_dev);
404+
port = rmnet_get_port_rtnl(real_dev);
413405

414406
/* If there is more than one rmnet dev attached, its probably being
415407
* used for muxing. Skip the briding in that case
416408
*/
417409
if (port->nr_rmnet_devs > 1)
418410
return -EINVAL;
419411

412+
if (port->rmnet_mode != RMNET_EPMODE_VND)
413+
return -EINVAL;
414+
420415
if (rmnet_is_real_dev_registered(slave_dev))
421416
return -EBUSY;
422417

423418
err = rmnet_register_real_device(slave_dev);
424419
if (err)
425420
return -EBUSY;
426421

427-
slave_port = rmnet_get_port(slave_dev);
422+
err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
423+
extack);
424+
if (err) {
425+
rmnet_unregister_real_device(slave_dev);
426+
return err;
427+
}
428+
429+
slave_port = rmnet_get_port_rtnl(slave_dev);
428430
slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
429431
slave_port->bridge_ep = real_dev;
432+
slave_port->rmnet_dev = rmnet_dev;
430433

431434
port->rmnet_mode = RMNET_EPMODE_BRIDGE;
432435
port->bridge_ep = slave_dev;
@@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
438441
int rmnet_del_bridge(struct net_device *rmnet_dev,
439442
struct net_device *slave_dev)
440443
{
441-
struct rmnet_priv *priv = netdev_priv(rmnet_dev);
442-
struct net_device *real_dev = priv->real_dev;
443-
struct rmnet_port *port, *slave_port;
444+
struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
444445

445-
port = rmnet_get_port(real_dev);
446-
port->rmnet_mode = RMNET_EPMODE_VND;
447-
port->bridge_ep = NULL;
448-
449-
slave_port = rmnet_get_port(slave_dev);
450-
rmnet_unregister_real_device(slave_dev, slave_port);
446+
rmnet_unregister_bridge(port);
451447

452448
netdev_dbg(slave_dev, "removed from rmnet as slave\n");
453449
return 0;
@@ -473,8 +469,8 @@ static int __init rmnet_init(void)
473469

474470
static void __exit rmnet_exit(void)
475471
{
476-
unregister_netdevice_notifier(&rmnet_dev_notifier);
477472
rtnl_link_unregister(&rmnet_link_ops);
473+
unregister_netdevice_notifier(&rmnet_dev_notifier);
478474
}
479475

480476
module_init(rmnet_init)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct rmnet_port {
2828
u8 rmnet_mode;
2929
struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
3030
struct net_device *bridge_ep;
31+
struct net_device *rmnet_dev;
3132
};
3233

3334
extern struct rtnl_link_ops rmnet_link_ops;
@@ -65,7 +66,7 @@ struct rmnet_priv {
6566
struct rmnet_priv_stats stats;
6667
};
6768

68-
struct rmnet_port *rmnet_get_port(struct net_device *real_dev);
69+
struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev);
6970
struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id);
7071
int rmnet_add_bridge(struct net_device *rmnet_dev,
7172
struct net_device *slave_dev,

0 commit comments

Comments
 (0)