Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69431f60 authored by Phil Sutter's avatar Phil Sutter Committed by Greg Kroah-Hartman
Browse files

netfilter: xt_owner: Fix for unsafe access of sk->sk_socket



[ Upstream commit 7ae836a3d630e146b732fe8ef7d86b243748751f ]

A concurrently running sock_orphan() may NULL the sk_socket pointer in
between check and deref. Follow other users (like nft_meta.c for
instance) and acquire sk_callback_lock before dereferencing sk_socket.

Fixes: 0265ab44 ("[NETFILTER]: merge ipt_owner/ip6t_owner in xt_owner")
Reported-by: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarPhil Sutter <phil@nwl.cc>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent c61c61d7
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -76,19 +76,24 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
		 */
		return false;

	filp = sk->sk_socket->file;
	if (filp == NULL)
	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);
		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))
		    !(info->invert & XT_OWNER_UID)) {
			read_unlock_bh(&sk->sk_callback_lock);
			return false;
		}
	}

	if (info->match & XT_OWNER_GID) {
		unsigned int i, match = false;
@@ -112,10 +117,13 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
			}
		}

		if (match ^ !(info->invert & XT_OWNER_GID))
		if (match ^ !(info->invert & XT_OWNER_GID)) {
			read_unlock_bh(&sk->sk_callback_lock);
			return false;
		}
	}

	read_unlock_bh(&sk->sk_callback_lock);
	return true;
}