diff options
| author | Eric Dumazet <edumazet@google.com> | 2026-02-25 16:23:19 +0300 |
|---|---|---|
| committer | Florian Westphal <fw@strlen.de> | 2026-03-04 13:45:44 +0300 |
| commit | cdec942ac2006d74b2219c5f950402e5bd1f6c7b (patch) | |
| tree | 8fa90ae2201eee27959cde1ed27da2e52d8689ee /net | |
| parent | 5663ac3e548163183c4354e75f728f7b34ffe040 (diff) | |
| download | linux-cdec942ac2006d74b2219c5f950402e5bd1f6c7b.tar.xz | |
netfilter: xt_owner: no longer acquire sk_callback_lock in mt_owner()
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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/netfilter/xt_owner.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index 50332888c8d2..5bfb4843df66 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c @@ -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; } |
