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: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
+17
-9
@@ -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(>p->list, &gn->gtp_dev_list);
|
||||
gn = net_generic(src_net, gtp_net_id);
|
||||
list_add(>p->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, >p->tid_hash[i], hlist_tid)
|
||||
pdp_context_delete(pctx);
|
||||
|
||||
list_del_rcu(>p->list);
|
||||
list_del(>p->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 != >p_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;
|
||||
|
||||
list_for_each_entry(gtp, &gn->gtp_dev_list, list)
|
||||
for_each_netdev(net, dev)
|
||||
if (dev->rtnl_link_ops == >p_link_ops)
|
||||
gtp_dellink(dev, dev_to_kill);
|
||||
|
||||
list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
|
||||
gtp_dellink(gtp->dev, dev_to_kill);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user