Commit 59f26d86 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

inet: ping: check sock_net() in ping_get_port() and ping_lookup()



We need to check socket netns before considering them in ping_get_port().
Otherwise, one malicious netns could 'consume' all ports.

Add corresponding check in ping_lookup().

Fixes: c319b4d7 ("net: ipv4: add IPPROTO_ICMP socket kind")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Link: https://patch.msgid.link/20250829153054.474201-2-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ec0b1eee
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ static inline struct hlist_head *ping_hashslot(struct ping_table *table,

int ping_get_port(struct sock *sk, unsigned short ident)
{
	struct net *net = sock_net(sk);
	struct inet_sock *isk, *isk2;
	struct hlist_head *hlist;
	struct sock *sk2 = NULL;
@@ -90,9 +91,10 @@ int ping_get_port(struct sock *sk, unsigned short ident)
		for (i = 0; i < (1L << 16); i++, result++) {
			if (!result)
				result++; /* avoid zero */
			hlist = ping_hashslot(&ping_table, sock_net(sk),
					    result);
			hlist = ping_hashslot(&ping_table, net, result);
			sk_for_each(sk2, hlist) {
				if (!net_eq(sock_net(sk2), net))
					continue;
				isk2 = inet_sk(sk2);

				if (isk2->inet_num == result)
@@ -108,8 +110,10 @@ int ping_get_port(struct sock *sk, unsigned short ident)
		if (i >= (1L << 16))
			goto fail;
	} else {
		hlist = ping_hashslot(&ping_table, sock_net(sk), ident);
		hlist = ping_hashslot(&ping_table, net, ident);
		sk_for_each(sk2, hlist) {
			if (!net_eq(sock_net(sk2), net))
				continue;
			isk2 = inet_sk(sk2);

			/* BUG? Why is this reuse and not reuseaddr? ping.c
@@ -129,7 +133,7 @@ int ping_get_port(struct sock *sk, unsigned short ident)
		pr_debug("was not hashed\n");
		sk_add_node_rcu(sk, hlist);
		sock_set_flag(sk, SOCK_RCU_FREE);
		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
		sock_prot_inuse_add(net, sk->sk_prot, 1);
	}
	spin_unlock(&ping_table.lock);
	return 0;
@@ -188,6 +192,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
	}

	sk_for_each_rcu(sk, hslot) {
		if (!net_eq(sock_net(sk), net))
			continue;
		isk = inet_sk(sk);

		pr_debug("iterate\n");