Skip to contentSkip to conversation

Patch "soreuseport: fix initialization race" has been added to the 4.13-stable tree

PATCH [email protected] 1 participant 1 message Nov 15, 2017

Subsystems (5)
Networking Stable branch TCP Sockets +1 more subsystems
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

soreuseport: fix initialization race

to the 4.13-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
soreuseport-fix-initialization-race.patch
and it can be found in the queue-4.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Wed Nov 15 17:25:34 CET 2017

From: Craig Gallek <[email protected]>
Date: Thu, 19 Oct 2017 15:00:29 -0400
Subject: soreuseport: fix initialization race

From: Craig Gallek <[email protected]>

[ Upstream commit 1b5f962e71bfad6284574655c406597535c3ea7a ]

Syzkaller stumbled upon a way to trigger

WARNING: CPU: 1 PID: 13881 at net/core/sock_reuseport.c:41
reuseport_alloc+0x306/0x3b0 net/core/sock_reuseport.c:39

There are two initialization paths for the sock_reuseport structure in a
socket: Through the udp/tcp bind paths of SO_REUSEPORT sockets or through SO_ATTACH_REUSEPORT_[CE]BPF before bind. The existing implementation assumedthat the socket lock protected both of these paths when it actually only protects the SO_ATTACH_REUSEPORT path. Syzkaller triggered this double allocation by running these paths concurrently.

This patch moves the check for double allocation into the reuseport_alloc function which is protected by a global spin lock.

Fixes e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection")
Fixes c125e80b8868 ("soreuseport: fast reuseport TCP socket selection")
---
 net/core/sock_reuseport.c  |   12 +++++++++---
 net/ipv4/inet_hashtables.c |    5 +----
 net/ipv4/udp.c             |    5 +----
 3 files changed, 11 insertions(+), 11 deletions(-)
net/core/sock_reuseport.c +9 -3
@@ -36,9 +36,14 @@ int reuseport_alloc(struct sock *sk)
 	 * soft irq of receive path or setsockopt from process context
 	 */
 	spin_lock_bh(&reuseport_lock);
-	WARN_ONCE(rcu_dereference_protected(sk->sk_reuseport_cb,
-					    lockdep_is_held(&reuseport_lock)),
-		  "multiple allocations for the same socket");
+
+	/* Allocation attempts can occur concurrently via the setsockopt path
+	 * and the bind/hash path.  Nothing to do when we lose the race.
+	 */
+	if (rcu_dereference_protected(sk->sk_reuseport_cb,
+				      lockdep_is_held(&reuseport_lock)))
+		goto out;
+
 	reuse = __reuseport_alloc(INIT_SOCKS);
 	if (!reuse) {
 		spin_unlock_bh(&reuseport_lock);
@@ -49,6 +54,7 @@ int reuseport_alloc(struct sock *sk)
 	reuse->num_socks = 1;
 	rcu_assign_pointer(sk->sk_reuseport_cb, reuse);
 
+out:
 	spin_unlock_bh(&reuseport_lock);
 
 	return 0;
net/ipv4/inet_hashtables.c +1 -4
@@ -449,10 +449,7 @@ static int inet_reuseport_add_sock(struc
 			return reuseport_add_sock(sk, sk2);
 	}
 
-	/* Initial allocation may have already happened via setsockopt */
-	if (!rcu_access_pointer(sk->sk_reuseport_cb))
-		return reuseport_alloc(sk);
-	return 0;
+	return reuseport_alloc(sk);
 }
 
 int __inet_hash(struct sock *sk, struct sock *osk)
net/ipv4/udp.c +1 -4
@@ -231,10 +231,7 @@ static int udp_reuseport_add_sock(struct
 		}
 	}
 
-	/* Initial allocation may have already happened via setsockopt */
-	if (!rcu_access_pointer(sk->sk_reuseport_cb))
-		return reuseport_alloc(sk);
-	return 0;
+	return reuseport_alloc(sk);
 }
 
 /**

Patches currently in stable-queue which might be from [email protected] are

queue-4.13/soreuseport-fix-initialization-race.patch queue-4.13/tun-tap-sanitize-tunsetsndbuf-input.patch