diff options
author | Craig Gallek <kraig@google.com> | 2016-01-19 20:27:08 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-01-19 20:44:23 +0100 |
commit | b4ace4f1ae07691b4f6ea9f3e92efbec083df058 (patch) | |
tree | 6845c5f7ff2e8994046ac9a41ea5d5ec00fd21ab /net/core | |
parent | af_iucv: Validate socket address length in iucv_sock_bind() (diff) | |
download | linux-b4ace4f1ae07691b4f6ea9f3e92efbec083df058.tar.xz linux-b4ace4f1ae07691b4f6ea9f3e92efbec083df058.zip |
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>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sock_reuseport.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index 1df98c557440..e92b759d906c 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c @@ -93,10 +93,17 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) * @sk2: Socket belonging to the existing reuseport group. * May return ENOMEM and not add socket to group under memory pressure. */ -int reuseport_add_sock(struct sock *sk, const struct sock *sk2) +int reuseport_add_sock(struct sock *sk, struct sock *sk2) { struct sock_reuseport *reuse; + if (!rcu_access_pointer(sk2->sk_reuseport_cb)) { + int err = reuseport_alloc(sk2); + + if (err) + return err; + } + spin_lock_bh(&reuseport_lock); reuse = rcu_dereference_protected(sk2->sk_reuseport_cb, lockdep_is_held(&reuseport_lock)), |