Commit 22ad81ac authored by Geliang Tang's avatar Geliang Tang
Browse files

inet: implement lockless IP_MULTICAST_TTL

mainline inclusion
from mainline-v6.7-rc1
commit e08d0b3d172311e2bb500865c0d0038533d0ff11
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9VYQ9
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=e08d0b3d172311e2bb500865c0d0038533d0ff11



--------------------------------

inet->mc_ttl can be read locklessly.

Implement proper lockless reads and writes to inet->mc_ttl

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Reviewed-by: default avatarJackie Liu <liuyun01@kylinos.cn>
Signed-off-by: default avatarGeliang Tang <tanggeliang@kylinos.cn>
parent 59d9c906
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1432,7 +1432,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
	if (cork->ttl != 0)
		ttl = cork->ttl;
	else if (rt->rt_type == RTN_MULTICAST)
		ttl = inet->mc_ttl;
		ttl = READ_ONCE(inet->mc_ttl);
	else
		ttl = ip_select_ttl(inet, &rt->dst);

+16 −15
Original line number Diff line number Diff line
@@ -1039,6 +1039,17 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,

		WRITE_ONCE(inet->min_ttl, val);
		return 0;
	case IP_MULTICAST_TTL:
		if (sk->sk_type == SOCK_STREAM)
			return -EINVAL;
		if (optlen < 1)
			return -EINVAL;
		if (val == -1)
			val = 1;
		if (val < 0 || val > 255)
			return -EINVAL;
		WRITE_ONCE(inet->mc_ttl, val);
		return 0;
	}

	err = 0;
@@ -1101,17 +1112,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
			goto e_inval;
		inet->pmtudisc = val;
		break;
	case IP_MULTICAST_TTL:
		if (sk->sk_type == SOCK_STREAM)
			goto e_inval;
		if (optlen < 1)
			goto e_inval;
		if (val == -1)
			val = 1;
		if (val < 0 || val > 255)
			goto e_inval;
		inet->mc_ttl = val;
		break;
	case IP_UNICAST_IF:
	{
		struct net_device *dev = NULL;
@@ -1594,6 +1594,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
	case IP_MINTTL:
		val = READ_ONCE(inet->min_ttl);
		goto copyval;
	case IP_MULTICAST_TTL:
		val = READ_ONCE(inet->mc_ttl);
		goto copyval;
	}

	if (needs_rtnl)
@@ -1651,9 +1654,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
		}
		break;
	}
	case IP_MULTICAST_TTL:
		val = inet->mc_ttl;
		break;
	case IP_UNICAST_IF:
		val = (__force int)htonl((__u32) inet->uc_index);
		break;
@@ -1720,7 +1720,8 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
			put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
		}
		if (inet_test_bit(TTL, sk)) {
			int hlim = inet->mc_ttl;
			int hlim = READ_ONCE(inet->mc_ttl);

			put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
		}
		if (inet_test_bit(TOS, sk)) {
+1 −1
Original line number Diff line number Diff line
@@ -1320,7 +1320,7 @@ static void set_mcast_ttl(struct sock *sk, u_char ttl)

	/* setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); */
	lock_sock(sk);
	inet->mc_ttl = ttl;
	WRITE_ONCE(inet->mc_ttl, ttl);
#ifdef CONFIG_IP_VS_IPV6
	if (sk->sk_family == AF_INET6) {
		struct ipv6_pinfo *np = inet6_sk(sk);