• Guillaume Nault's avatar
    l2tp: fix racy socket lookup in l2tp_ip and l2tp_ip6 bind() · d5e3a190
    Guillaume Nault authored
    It's not enough to check for sockets bound to same address at the
    beginning of l2tp_ip{,6}_bind(): even if no socket is found at that
    time, a socket with the same address could be bound before we take
    the l2tp lock again.
    
    This patch moves the lookup right before inserting the new socket, so
    that no change can ever happen to the list between address lookup and
    socket insertion.
    
    Care is taken to avoid side effects on the socket in case of failure.
    That is, modifications of the socket are done after the lookup, when
    binding is guaranteed to succeed, and before releasing the l2tp lock,
    so that concurrent lookups will always see fully initialised sockets.
    
    For l2tp_ip, 'ret' is set to -EINVAL before checking the SOCK_ZAPPED
    bit. Error code was mistakenly set to -EADDRINUSE on error by commit
    32c23116 ("l2tp: fix racy SOCK_ZAPPED flag check in l2tp_ip{,6}_bind()").
    Using -EINVAL restores original behaviour.
    
    For l2tp_ip6, the lookup is now always done with the correct bound
    device. Before this patch, when binding to a link-local address, the
    lookup was done with the original sk->sk_bound_dev_if, which was later
    overwritten with addr->l2tp_scope_id. Lookup is now performed with the
    final sk->sk_bound_dev_if value.
    
    Finally, the (addr_len >= sizeof(struct sockaddr_in6)) check has been
    dropped: addr is a sockaddr_l2tpip6 not sockaddr_in6 and addr_len has
    already been checked at this point (this part of the code seems to have
    been copy-pasted from net/ipv6/raw.c).
    Signed-off-by: default avatarGuillaume Nault <g.nault@alphalink.fr>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    d5e3a190
l2tp_ip.c 15.9 KB