Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soreuseport: fix NULL ptr dereference SO_REUSEPORT after bind

Marc Dionne discovered a NULL pointer dereference when setting
SO_REUSEPORT on a socket after it is bound.
This patch removes the assumption that at least one socket in the
reuseport group is bound with the SO_REUSEPORT option before other
bind calls occur.

Fixes: e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection")
Reported-by: Marc Dionne <marc.c.dionne@gmail.com>
Signed-off-by: Craig Gallek <kraig@google.com>
Tested-by: Marc Dionne <marc.dionne@auristor.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Craig Gallek and committed by
David S. Miller
b4ace4f1 52a82e23

+9 -2
+1 -1
include/net/sock_reuseport.h
··· 16 16 }; 17 17 18 18 extern int reuseport_alloc(struct sock *sk); 19 - extern int reuseport_add_sock(struct sock *sk, const struct sock *sk2); 19 + extern int reuseport_add_sock(struct sock *sk, struct sock *sk2); 20 20 extern void reuseport_detach_sock(struct sock *sk); 21 21 extern struct sock *reuseport_select_sock(struct sock *sk, 22 22 u32 hash,
+8 -1
net/core/sock_reuseport.c
··· 93 93 * @sk2: Socket belonging to the existing reuseport group. 94 94 * May return ENOMEM and not add socket to group under memory pressure. 95 95 */ 96 - int reuseport_add_sock(struct sock *sk, const struct sock *sk2) 96 + int reuseport_add_sock(struct sock *sk, struct sock *sk2) 97 97 { 98 98 struct sock_reuseport *reuse; 99 + 100 + if (!rcu_access_pointer(sk2->sk_reuseport_cb)) { 101 + int err = reuseport_alloc(sk2); 102 + 103 + if (err) 104 + return err; 105 + } 99 106 100 107 spin_lock_bh(&reuseport_lock); 101 108 reuse = rcu_dereference_protected(sk2->sk_reuseport_cb,