Skip to content

Commit

Permalink
Merge branch 'gtp-pfcp-fix-use-after-free-of-udp-tunnel-socket'
Browse files Browse the repository at this point in the history
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/20250104125732.17335-1-shaw.leon@gmail.com/

Changes:
  v2:
    * Patch 1
      * Fix uninit/unused local var

  v1: https://lore.kernel.org/netdev/20250108062834.11117-1-kuniyu@amazon.com/
====================

Link: https://patch.msgid.link/20250110014754.33847-1-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Jan 14, 2025
2 parents 644f910 + ffc90e9 commit 0865b9f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
26 changes: 17 additions & 9 deletions drivers/net/gtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1524,8 +1524,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
goto out_encap;
}

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

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

list_del_rcu(&gtp->list);
list_del(&gtp->list);
unregister_netdevice_queue(dev, head);
}

Expand Down Expand Up @@ -2271,16 +2271,19 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
int i, j, bucket = cb->args[0], skip = cb->args[1];
struct net *net = sock_net(skb->sk);
struct net_device *dev;
struct pdp_ctx *pctx;
struct gtp_net *gn;

gn = net_generic(net, gtp_net_id);

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

rcu_read_lock();
list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
for_each_netdev_rcu(net, dev) {
if (dev->rtnl_link_ops != &gtp_link_ops)
continue;

gtp = netdev_priv(dev);

if (last_gtp && last_gtp != gtp)
continue;
else
Expand Down Expand Up @@ -2475,9 +2478,14 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,

list_for_each_entry(net, net_list, exit_list) {
struct gtp_net *gn = net_generic(net, gtp_net_id);
struct gtp_dev *gtp;
struct gtp_dev *gtp, *gtp_next;
struct net_device *dev;

for_each_netdev(net, dev)
if (dev->rtnl_link_ops == &gtp_link_ops)
gtp_dellink(dev, dev_to_kill);

list_for_each_entry(gtp, &gn->gtp_dev_list, list)
list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
gtp_dellink(gtp->dev, dev_to_kill);
}
}
Expand Down
15 changes: 10 additions & 5 deletions drivers/net/pfcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ static int pfcp_newlink(struct net *net, struct net_device *dev,
goto exit_del_pfcp_sock;
}

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

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

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

list_del_rcu(&pfcp->list);
list_del(&pfcp->list);
unregister_netdevice_queue(dev, head);
}

Expand All @@ -247,11 +247,16 @@ static int __net_init pfcp_net_init(struct net *net)
static void __net_exit pfcp_net_exit(struct net *net)
{
struct pfcp_net *pn = net_generic(net, pfcp_net_id);
struct pfcp_dev *pfcp;
struct pfcp_dev *pfcp, *pfcp_next;
struct net_device *dev;
LIST_HEAD(list);

rtnl_lock();
list_for_each_entry(pfcp, &pn->pfcp_dev_list, list)
for_each_netdev(net, dev)
if (dev->rtnl_link_ops == &pfcp_link_ops)
pfcp_dellink(dev, &list);

list_for_each_entry_safe(pfcp, pfcp_next, &pn->pfcp_dev_list, list)
pfcp_dellink(pfcp->dev, &list);

unregister_netdevice_many(&list);
Expand Down

0 comments on commit 0865b9f

Please sign in to comment.