• Martin KaFai Lau's avatar
    net: inet_csk: Fix so_reuseport bind-address cache in tb->fast* · 88d7fcfa
    Martin KaFai Lau authored
    The commit 637bc8bb ("inet: reset tb->fastreuseport when adding a reuseport sk")
    added a bind-address cache in tb->fast*.  The tb->fast* caches the address
    of a sk which has successfully been binded with SO_REUSEPORT ON.  The idea
    is to avoid the expensive conflict search in inet_csk_bind_conflict().
    
    There is an issue with wildcard matching where sk_reuseport_match() should
    have returned false but it is currently returning true.  It ends up
    hiding bind conflict.  For example,
    
    bind("[::1]:443"); /* without SO_REUSEPORT. Succeed. */
    bind("[::2]:443"); /* with    SO_REUSEPORT. Succeed. */
    bind("[::]:443");  /* with    SO_REUSEPORT. Still Succeed where it shouldn't */
    
    The last bind("[::]:443") with SO_REUSEPORT on should have failed because
    it should have a conflict with the very first bind("[::1]:443") which
    has SO_REUSEPORT off.  However, the address "[::2]" is cached in
    tb->fast* in the second bind. In the last bind, the sk_reuseport_match()
    returns true because the binding sk's wildcard addr "[::]" matches with
    the "[::2]" cached in tb->fast*.
    
    The correct bind conflict is reported by removing the second
    bind such that tb->fast* cache is not involved and forces the
    bind("[::]:443") to go through the inet_csk_bind_conflict():
    
    bind("[::1]:443"); /* without SO_REUSEPORT. Succeed. */
    bind("[::]:443");  /* with    SO_REUSEPORT. -EADDRINUSE */
    
    The expected behavior for sk_reuseport_match() is, it should only allow
    the "cached" tb->fast* address to be used as a wildcard match but not
    the address of the binding sk.  To do that, the current
    "bool match_wildcard" arg is split into
    "bool match_sk1_wildcard" and "bool match_sk2_wildcard".
    
    This change only affects the sk_reuseport_match() which is only
    used by inet_csk (e.g. TCP).
    The other use cases are calling inet_rcv_saddr_equal() and
    this patch makes it pass the same "match_wildcard" arg twice to
    the "ipv[46]_rcv_saddr_equal(..., match_wildcard, match_wildcard)".
    
    Cc: Josef Bacik <jbacik@fb.com>
    Fixes: 637bc8bb ("inet: reset tb->fastreuseport when adding a reuseport sk")
    Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    88d7fcfa
inet_connection_sock.c 31.7 KB