Commit 0865b9fd authored by Paolo Abeni's avatar Paolo Abeni
Browse files

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/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: default avatarPaolo Abeni <pabeni@redhat.com>
parents 644f9108 ffc90e9c
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -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");
@@ -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);
}

@@ -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
@@ -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);
	}
}
+10 −5
Original line number Diff line number Diff line
@@ -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");

@@ -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);
}

@@ -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);