Commit 859f8b26 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

ipv6: lockless IPV6_FLOWINFO_SEND implementation



np->sndflow reads are racy.

Use one bit ftom atomic inet->inet_flags instead,
IPV6_FLOWINFO_SEND setsockopt() can be lockless.

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>
parent 6b724bc4
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -243,8 +243,7 @@ struct ipv6_pinfo {
	} rxopt;

	/* sockopt flags */
	__u8			sndflow:1,
				srcprefs:3;	/* 001: prefer temporary address
	__u8			srcprefs:3;	/* 001: prefer temporary address
						 * 010: prefer public address
						 * 100: prefer care-of address
						 */
+1 −0
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ enum {
	INET_FLAGS_RECVERR6	= 26,
	INET_FLAGS_REPFLOW	= 27,
	INET_FLAGS_RTALERT_ISOLATE = 28,
	INET_FLAGS_SNDFLOW	= 29,
};

/* cmsg flags for inet */
+1 −1
Original line number Diff line number Diff line
@@ -844,7 +844,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,

	memset(&fl6, 0, sizeof(fl6));

	if (np->sndflow) {
	if (inet6_test_bit(SNDFLOW, sk)) {
		fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
		IP6_ECN_flow_init(fl6.flowlabel);
		if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
+1 −2
Original line number Diff line number Diff line
@@ -899,7 +899,6 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,

#if IS_ENABLED(CONFIG_IPV6)
	} else if (family == AF_INET6) {
		struct ipv6_pinfo *np = inet6_sk(sk);
		struct ipv6hdr *ip6 = ipv6_hdr(skb);
		DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);

@@ -908,7 +907,7 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
			sin6->sin6_port = 0;
			sin6->sin6_addr = ip6->saddr;
			sin6->sin6_flowinfo = 0;
			if (np->sndflow)
			if (inet6_test_bit(SNDFLOW, sk))
				sin6->sin6_flowinfo = ip6_flowinfo(ip6);
			sin6->sin6_scope_id =
				ipv6_iface_scope_id(&sin6->sin6_addr,
+1 −1
Original line number Diff line number Diff line
@@ -537,7 +537,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
		}
		sin->sin6_port = inet->inet_dport;
		sin->sin6_addr = sk->sk_v6_daddr;
		if (np->sndflow)
		if (inet6_test_bit(SNDFLOW, sk))
			sin->sin6_flowinfo = np->flow_label;
		BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
				       CGROUP_INET6_GETPEERNAME);
Loading