Skip to content

Commit 0865b9f

Browse files
author
Paolo Abeni
committed
Merge branch 'gtp-pfcp-fix-use-after-free-of-udp-tunnel-socket'
Kuniyuki Iwashima says: ==================== gtp/pfcp: Fix use-after-free of UDP tunnel socket. Xiao Liang pointed out weird netns usages in ->newlink() of gtp and pfcp. This series fixes the issues. Link: https://lore.kernel.org/netdev/[email protected]/ Changes: v2: * Patch 1 * Fix uninit/unused local var v1: https://lore.kernel.org/netdev/[email protected]/ ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 644f910 + ffc90e9 commit 0865b9f

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

drivers/net/gtp.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,8 +1524,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
15241524
goto out_encap;
15251525
}
15261526

1527-
gn = net_generic(dev_net(dev), gtp_net_id);
1528-
list_add_rcu(&gtp->list, &gn->gtp_dev_list);
1527+
gn = net_generic(src_net, gtp_net_id);
1528+
list_add(&gtp->list, &gn->gtp_dev_list);
15291529
dev->priv_destructor = gtp_destructor;
15301530

15311531
netdev_dbg(dev, "registered new GTP interface\n");
@@ -1551,7 +1551,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head)
15511551
hlist_for_each_entry_safe(pctx, next, &gtp->tid_hash[i], hlist_tid)
15521552
pdp_context_delete(pctx);
15531553

1554-
list_del_rcu(&gtp->list);
1554+
list_del(&gtp->list);
15551555
unregister_netdevice_queue(dev, head);
15561556
}
15571557

@@ -2271,16 +2271,19 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
22712271
struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
22722272
int i, j, bucket = cb->args[0], skip = cb->args[1];
22732273
struct net *net = sock_net(skb->sk);
2274+
struct net_device *dev;
22742275
struct pdp_ctx *pctx;
2275-
struct gtp_net *gn;
2276-
2277-
gn = net_generic(net, gtp_net_id);
22782276

22792277
if (cb->args[4])
22802278
return 0;
22812279

22822280
rcu_read_lock();
2283-
list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
2281+
for_each_netdev_rcu(net, dev) {
2282+
if (dev->rtnl_link_ops != &gtp_link_ops)
2283+
continue;
2284+
2285+
gtp = netdev_priv(dev);
2286+
22842287
if (last_gtp && last_gtp != gtp)
22852288
continue;
22862289
else
@@ -2475,9 +2478,14 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
24752478

24762479
list_for_each_entry(net, net_list, exit_list) {
24772480
struct gtp_net *gn = net_generic(net, gtp_net_id);
2478-
struct gtp_dev *gtp;
2481+
struct gtp_dev *gtp, *gtp_next;
2482+
struct net_device *dev;
2483+
2484+
for_each_netdev(net, dev)
2485+
if (dev->rtnl_link_ops == &gtp_link_ops)
2486+
gtp_dellink(dev, dev_to_kill);
24792487

2480-
list_for_each_entry(gtp, &gn->gtp_dev_list, list)
2488+
list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
24812489
gtp_dellink(gtp->dev, dev_to_kill);
24822490
}
24832491
}

drivers/net/pfcp.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ static int pfcp_newlink(struct net *net, struct net_device *dev,
206206
goto exit_del_pfcp_sock;
207207
}
208208

209-
pn = net_generic(dev_net(dev), pfcp_net_id);
210-
list_add_rcu(&pfcp->list, &pn->pfcp_dev_list);
209+
pn = net_generic(net, pfcp_net_id);
210+
list_add(&pfcp->list, &pn->pfcp_dev_list);
211211

212212
netdev_dbg(dev, "registered new PFCP interface\n");
213213

@@ -224,7 +224,7 @@ static void pfcp_dellink(struct net_device *dev, struct list_head *head)
224224
{
225225
struct pfcp_dev *pfcp = netdev_priv(dev);
226226

227-
list_del_rcu(&pfcp->list);
227+
list_del(&pfcp->list);
228228
unregister_netdevice_queue(dev, head);
229229
}
230230

@@ -247,11 +247,16 @@ static int __net_init pfcp_net_init(struct net *net)
247247
static void __net_exit pfcp_net_exit(struct net *net)
248248
{
249249
struct pfcp_net *pn = net_generic(net, pfcp_net_id);
250-
struct pfcp_dev *pfcp;
250+
struct pfcp_dev *pfcp, *pfcp_next;
251+
struct net_device *dev;
251252
LIST_HEAD(list);
252253

253254
rtnl_lock();
254-
list_for_each_entry(pfcp, &pn->pfcp_dev_list, list)
255+
for_each_netdev(net, dev)
256+
if (dev->rtnl_link_ops == &pfcp_link_ops)
257+
pfcp_dellink(dev, &list);
258+
259+
list_for_each_entry_safe(pfcp, pfcp_next, &pn->pfcp_dev_list, list)
255260
pfcp_dellink(pfcp->dev, &list);
256261

257262
unregister_netdevice_many(&list);

0 commit comments

Comments
 (0)