Commit 2fd4161d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'inet-ping-misc-changes'

Eric Dumazet says:

====================
inet: ping: misc changes

First and third patches improve security a bit.

Second patch (ping_hash removal) is a cleanup.

Fourth patch uses EXPORT_IPV6_MOD[_GPL].
====================

Link: https://patch.msgid.link/20250829153054.474201-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ec0b1eee 51ba2d26
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -251,6 +251,7 @@ struct netns_ipv4 {
	int sysctl_igmp_qrv;

	struct ping_group_range ping_group_range;
	u16			ping_port_rover;

	atomic_t dev_addr_genid;

+0 −1
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ struct pingfakehdr {
};

int  ping_get_port(struct sock *sk, unsigned short ident);
int ping_hash(struct sock *sk);
void ping_unhash(struct sock *sk);

int  ping_init_sock(struct sock *sk);
+31 −35
Original line number Diff line number Diff line
@@ -56,9 +56,7 @@ struct ping_table {

static struct ping_table ping_table;
struct pingv6_ops pingv6_ops;
EXPORT_SYMBOL_GPL(pingv6_ops);

static u16 ping_port_rover;
EXPORT_IPV6_MOD_GPL(pingv6_ops);

static inline u32 ping_hashfn(const struct net *net, u32 num, u32 mask)
{
@@ -67,7 +65,6 @@ static inline u32 ping_hashfn(const struct net *net, u32 num, u32 mask)
	pr_debug("hash(%u) = %u\n", num, res);
	return res;
}
EXPORT_SYMBOL_GPL(ping_hash);

static inline struct hlist_head *ping_hashslot(struct ping_table *table,
					       struct net *net, unsigned int num)
@@ -77,6 +74,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;
@@ -84,15 +82,16 @@ int ping_get_port(struct sock *sk, unsigned short ident)
	isk = inet_sk(sk);
	spin_lock(&ping_table.lock);
	if (ident == 0) {
		u16 result = net->ipv4.ping_port_rover + 1;
		u32 i;
		u16 result = ping_port_rover + 1;

		for (i = 0; i < (1L << 16); i++, result++) {
			if (!result)
				result++; /* avoid zero */
			hlist = ping_hashslot(&ping_table, sock_net(sk),
					    result);
				continue; /* avoid zero */
			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)
@@ -100,7 +99,7 @@ int ping_get_port(struct sock *sk, unsigned short ident)
			}

			/* found */
			ping_port_rover = ident = result;
			net->ipv4.ping_port_rover = ident = result;
			break;
next_port:
			;
@@ -108,8 +107,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 +130,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;
@@ -138,15 +139,7 @@ int ping_get_port(struct sock *sk, unsigned short ident)
	spin_unlock(&ping_table.lock);
	return -EADDRINUSE;
}
EXPORT_SYMBOL_GPL(ping_get_port);

int ping_hash(struct sock *sk)
{
	pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num);
	BUG(); /* "Please do not press this button again." */

	return 0;
}
EXPORT_IPV6_MOD_GPL(ping_get_port);

void ping_unhash(struct sock *sk)
{
@@ -161,7 +154,7 @@ void ping_unhash(struct sock *sk)
	}
	spin_unlock(&ping_table.lock);
}
EXPORT_SYMBOL_GPL(ping_unhash);
EXPORT_IPV6_MOD_GPL(ping_unhash);

/* Called under rcu_read_lock() */
static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
@@ -188,6 +181,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");
@@ -279,7 +274,7 @@ int ping_init_sock(struct sock *sk)
	put_group_info(group_info);
	return ret;
}
EXPORT_SYMBOL_GPL(ping_init_sock);
EXPORT_IPV6_MOD_GPL(ping_init_sock);

void ping_close(struct sock *sk, long timeout)
{
@@ -289,7 +284,7 @@ void ping_close(struct sock *sk, long timeout)

	sk_common_release(sk);
}
EXPORT_SYMBOL_GPL(ping_close);
EXPORT_IPV6_MOD_GPL(ping_close);

static int ping_pre_connect(struct sock *sk, struct sockaddr *uaddr,
			    int addr_len)
@@ -467,7 +462,7 @@ int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
	pr_debug("ping_v4_bind -> %d\n", err);
	return err;
}
EXPORT_SYMBOL_GPL(ping_bind);
EXPORT_IPV6_MOD_GPL(ping_bind);

/*
 * Is this a supported type of ICMP message?
@@ -600,7 +595,7 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
out:
	return;
}
EXPORT_SYMBOL_GPL(ping_err);
EXPORT_IPV6_MOD_GPL(ping_err);

/*
 *	Copy and checksum an ICMP Echo packet from user space into a buffer
@@ -630,7 +625,7 @@ int ping_getfrag(void *from, char *to,

	return 0;
}
EXPORT_SYMBOL_GPL(ping_getfrag);
EXPORT_IPV6_MOD_GPL(ping_getfrag);

static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
				       struct flowi4 *fl4)
@@ -691,7 +686,7 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,

	return 0;
}
EXPORT_SYMBOL_GPL(ping_common_sendmsg);
EXPORT_IPV6_MOD_GPL(ping_common_sendmsg);

static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
@@ -936,7 +931,7 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
	pr_debug("ping_recvmsg -> %d\n", err);
	return err;
}
EXPORT_SYMBOL_GPL(ping_recvmsg);
EXPORT_IPV6_MOD_GPL(ping_recvmsg);

static enum skb_drop_reason __ping_queue_rcv_skb(struct sock *sk,
						 struct sk_buff *skb)
@@ -957,7 +952,7 @@ int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
	return __ping_queue_rcv_skb(sk, skb) ? -1 : 0;
}
EXPORT_SYMBOL_GPL(ping_queue_rcv_skb);
EXPORT_IPV6_MOD_GPL(ping_queue_rcv_skb);


/*
@@ -985,7 +980,7 @@ enum skb_drop_reason ping_rcv(struct sk_buff *skb)
	kfree_skb_reason(skb, SKB_DROP_REASON_NO_SOCKET);
	return SKB_DROP_REASON_NO_SOCKET;
}
EXPORT_SYMBOL_GPL(ping_rcv);
EXPORT_IPV6_MOD_GPL(ping_rcv);

struct proto ping_prot = {
	.name =		"PING",
@@ -1002,13 +997,12 @@ struct proto ping_prot = {
	.bind =		ping_bind,
	.backlog_rcv =	ping_queue_rcv_skb,
	.release_cb =	ip4_datagram_release_cb,
	.hash =		ping_hash,
	.unhash =	ping_unhash,
	.get_port =	ping_get_port,
	.put_port =	ping_unhash,
	.obj_size =	sizeof(struct inet_sock),
};
EXPORT_SYMBOL(ping_prot);
EXPORT_IPV6_MOD(ping_prot);

#ifdef CONFIG_PROC_FS

@@ -1073,7 +1067,7 @@ void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)

	return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
}
EXPORT_SYMBOL_GPL(ping_seq_start);
EXPORT_IPV6_MOD_GPL(ping_seq_start);

static void *ping_v4_seq_start(struct seq_file *seq, loff_t *pos)
{
@@ -1092,14 +1086,14 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
	++*pos;
	return sk;
}
EXPORT_SYMBOL_GPL(ping_seq_next);
EXPORT_IPV6_MOD_GPL(ping_seq_next);

void ping_seq_stop(struct seq_file *seq, void *v)
	__releases(ping_table.lock)
{
	spin_unlock(&ping_table.lock);
}
EXPORT_SYMBOL_GPL(ping_seq_stop);
EXPORT_IPV6_MOD_GPL(ping_seq_stop);

static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
		int bucket)
@@ -1150,6 +1144,8 @@ static int __net_init ping_v4_proc_init_net(struct net *net)
	if (!proc_create_net("icmp", 0444, net->proc_net, &ping_v4_seq_ops,
			sizeof(struct ping_iter_state)))
		return -ENOMEM;

	net->ipv4.ping_port_rover = get_random_u16();
	return 0;
}

+0 −1
Original line number Diff line number Diff line
@@ -208,7 +208,6 @@ struct proto pingv6_prot = {
	.recvmsg =	ping_recvmsg,
	.bind =		ping_bind,
	.backlog_rcv =	ping_queue_rcv_skb,
	.hash =		ping_hash,
	.unhash =	ping_unhash,
	.get_port =	ping_get_port,
	.put_port =	ping_unhash,