]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
openvswitch: use RCU protection in ovs_vport_cmd_fill_info()
authorEric Dumazet <edumazet@google.com>
Fri, 7 Feb 2025 13:58:37 +0000 (13:58 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 11 Feb 2025 02:09:09 +0000 (18:09 -0800)
ovs_vport_cmd_fill_info() can be called without RTNL or RCU.

Use RCU protection and dev_net_rcu() to avoid potential UAF.

Fixes: 9354d4520342 ("openvswitch: reliable interface indentification in port dumps")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250207135841.1948589-6-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/openvswitch/datapath.c

index 225f6048867f4a396f6411c50b0cdf9437303e97..5d548eda742dfc43fcd3d07458704ee9b7e9ed64 100644 (file)
@@ -2101,6 +2101,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
 {
        struct ovs_header *ovs_header;
        struct ovs_vport_stats vport_stats;
+       struct net *net_vport;
        int err;
 
        ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family,
@@ -2117,12 +2118,15 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
            nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex))
                goto nla_put_failure;
 
-       if (!net_eq(net, dev_net(vport->dev))) {
-               int id = peernet2id_alloc(net, dev_net(vport->dev), gfp);
+       rcu_read_lock();
+       net_vport = dev_net_rcu(vport->dev);
+       if (!net_eq(net, net_vport)) {
+               int id = peernet2id_alloc(net, net_vport, GFP_ATOMIC);
 
                if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
-                       goto nla_put_failure;
+                       goto nla_put_failure_unlock;
        }
+       rcu_read_unlock();
 
        ovs_vport_get_stats(vport, &vport_stats);
        if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
@@ -2143,6 +2147,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
        genlmsg_end(skb, ovs_header);
        return 0;
 
+nla_put_failure_unlock:
+       rcu_read_unlock();
 nla_put_failure:
        err = -EMSGSIZE;
 error: