Commit cdec942a authored by Eric Dumazet's avatar Eric Dumazet Committed by Florian Westphal
Browse files

netfilter: xt_owner: no longer acquire sk_callback_lock in mt_owner()



After commit 983512f3 ("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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
parent 5663ac3e
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -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,24 +77,26 @@ 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) {
		unsigned int i, match = false;
@@ -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;
}