]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: xt_owner: no longer acquire sk_callback_lock in mt_owner()
authorEric Dumazet <edumazet@google.com>
Wed, 25 Feb 2026 13:23:19 +0000 (13:23 +0000)
committerFlorian Westphal <fw@strlen.de>
Wed, 4 Mar 2026 10:45:44 +0000 (11:45 +0100)
After commit 983512f3a87f ("net: Drop the lock in skb_may_tx_timestamp()")
from Sebastian Andrzej Siewior, apply the same logic in mt_owner()
to avoid touching sk_callback_lock.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
net/netfilter/xt_owner.c

index 50332888c8d233aab0915a31f2f616f3171da45e..5bfb4843df66361a930b0b2ed8ad936d5a38eeba 100644 (file)
@@ -63,11 +63,12 @@ static bool
 owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
        const struct xt_owner_match_info *info = par->matchinfo;
-       const struct file *filp;
        struct sock *sk = skb_to_full_sk(skb);
        struct net *net = xt_net(par);
+       const struct socket *sock;
+       const struct file *filp;
 
-       if (!sk || !sk->sk_socket || !net_eq(net, sock_net(sk)))
+       if (!sk || !READ_ONCE(sk->sk_socket) || !net_eq(net, sock_net(sk)))
                return (info->match ^ info->invert) == 0;
        else if (info->match & info->invert & XT_OWNER_SOCKET)
                /*
@@ -76,23 +77,25 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
                 */
                return false;
 
-       read_lock_bh(&sk->sk_callback_lock);
-       filp = sk->sk_socket ? sk->sk_socket->file : NULL;
-       if (filp == NULL) {
-               read_unlock_bh(&sk->sk_callback_lock);
+       /* The sk pointer remains valid as long as the skb is. The sk_socket and
+        * file pointer may become NULL if the socket is closed. Both structures
+        * (including file->cred) are RCU freed which means they can be accessed
+        * within a RCU read section.
+        */
+       sock = READ_ONCE(sk->sk_socket);
+       filp = sock ? READ_ONCE(sock->file) : NULL;
+       if (filp == NULL)
                return ((info->match ^ info->invert) &
                       (XT_OWNER_UID | XT_OWNER_GID)) == 0;
-       }
 
        if (info->match & XT_OWNER_UID) {
                kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
                kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
+
                if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
                     uid_lte(filp->f_cred->fsuid, uid_max)) ^
-                   !(info->invert & XT_OWNER_UID)) {
-                       read_unlock_bh(&sk->sk_callback_lock);
+                   !(info->invert & XT_OWNER_UID))
                        return false;
-               }
        }
 
        if (info->match & XT_OWNER_GID) {
@@ -117,13 +120,10 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
                        }
                }
 
-               if (match ^ !(info->invert & XT_OWNER_GID)) {
-                       read_unlock_bh(&sk->sk_callback_lock);
+               if (match ^ !(info->invert & XT_OWNER_GID))
                        return false;
-               }
        }
 
-       read_unlock_bh(&sk->sk_callback_lock);
        return true;
 }