lkml.org 
[lkml]   [2022]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 006/163] secure_seq: use the 64 bits of the siphash for port offset calculation
    Date
    From: Willy Tarreau <w@1wt.eu>

    commit b2d057560b8107c633b39aabe517ff9d93f285e3 upstream.

    SipHash replaced MD5 in secure_ipv{4,6}_port_ephemeral() via commit
    7cd23e5300c1 ("secure_seq: use SipHash in place of MD5"), but the output
    remained truncated to 32-bit only. In order to exploit more bits from the
    hash, let's make the functions return the full 64-bit of siphash_3u32().
    We also make sure the port offset calculation in __inet_hash_connect()
    remains done on 32-bit to avoid the need for div_u64_rem() and an extra
    cost on 32-bit systems.

    Cc: Jason A. Donenfeld <Jason@zx2c4.com>
    Cc: Moshe Kol <moshe.kol@mail.huji.ac.il>
    Cc: Yossi Gilad <yossi.gilad@mail.huji.ac.il>
    Cc: Amit Klein <aksecurity@gmail.com>
    Reviewed-by: Eric Dumazet <edumazet@google.com>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    Signed-off-by: Jakub Kicinski <kuba@kernel.org>
    [SG: Adjusted context]
    Signed-off-by: Stefan Ghinea <stefan.ghinea@windriver.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/net/inet_hashtables.h | 2 +-
    include/net/secure_seq.h | 4 ++--
    net/core/secure_seq.c | 4 ++--
    net/ipv4/inet_hashtables.c | 10 ++++++----
    net/ipv6/inet6_hashtables.c | 4 ++--
    5 files changed, 13 insertions(+), 11 deletions(-)

    --- a/include/net/inet_hashtables.h
    +++ b/include/net/inet_hashtables.h
    @@ -419,7 +419,7 @@ static inline void sk_rcv_saddr_set(stru
    }

    int __inet_hash_connect(struct inet_timewait_death_row *death_row,
    - struct sock *sk, u32 port_offset,
    + struct sock *sk, u64 port_offset,
    int (*check_established)(struct inet_timewait_death_row *,
    struct sock *, __u16,
    struct inet_timewait_sock **));
    --- a/include/net/secure_seq.h
    +++ b/include/net/secure_seq.h
    @@ -4,8 +4,8 @@

    #include <linux/types.h>

    -u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
    -u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
    +u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
    +u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
    __be16 dport);
    u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
    __be16 sport, __be16 dport);
    --- a/net/core/secure_seq.c
    +++ b/net/core/secure_seq.c
    @@ -96,7 +96,7 @@ u32 secure_tcpv6_seq(const __be32 *saddr
    }
    EXPORT_SYMBOL(secure_tcpv6_seq);

    -u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
    +u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
    __be16 dport)
    {
    const struct {
    @@ -146,7 +146,7 @@ u32 secure_tcp_seq(__be32 saddr, __be32
    }
    EXPORT_SYMBOL_GPL(secure_tcp_seq);

    -u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
    +u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
    {
    net_secret_init();
    return siphash_4u32((__force u32)saddr, (__force u32)daddr,
    --- a/net/ipv4/inet_hashtables.c
    +++ b/net/ipv4/inet_hashtables.c
    @@ -504,7 +504,7 @@ not_unique:
    return -EADDRNOTAVAIL;
    }

    -static u32 inet_sk_port_offset(const struct sock *sk)
    +static u64 inet_sk_port_offset(const struct sock *sk)
    {
    const struct inet_sock *inet = inet_sk(sk);

    @@ -734,7 +734,7 @@ EXPORT_SYMBOL_GPL(inet_unhash);
    static u32 table_perturb[1 << INET_TABLE_PERTURB_SHIFT];

    int __inet_hash_connect(struct inet_timewait_death_row *death_row,
    - struct sock *sk, u32 port_offset,
    + struct sock *sk, u64 port_offset,
    int (*check_established)(struct inet_timewait_death_row *,
    struct sock *, __u16, struct inet_timewait_sock **))
    {
    @@ -777,7 +777,9 @@ int __inet_hash_connect(struct inet_time
    net_get_random_once(table_perturb, sizeof(table_perturb));
    index = hash_32(port_offset, INET_TABLE_PERTURB_SHIFT);

    - offset = (READ_ONCE(table_perturb[index]) + port_offset) % remaining;
    + offset = READ_ONCE(table_perturb[index]) + port_offset;
    + offset %= remaining;
    +
    /* In first pass we try ports of @low parity.
    * inet_csk_get_port() does the opposite choice.
    */
    @@ -854,7 +856,7 @@ ok:
    int inet_hash_connect(struct inet_timewait_death_row *death_row,
    struct sock *sk)
    {
    - u32 port_offset = 0;
    + u64 port_offset = 0;

    if (!inet_sk(sk)->inet_num)
    port_offset = inet_sk_port_offset(sk);
    --- a/net/ipv6/inet6_hashtables.c
    +++ b/net/ipv6/inet6_hashtables.c
    @@ -308,7 +308,7 @@ not_unique:
    return -EADDRNOTAVAIL;
    }

    -static u32 inet6_sk_port_offset(const struct sock *sk)
    +static u64 inet6_sk_port_offset(const struct sock *sk)
    {
    const struct inet_sock *inet = inet_sk(sk);

    @@ -320,7 +320,7 @@ static u32 inet6_sk_port_offset(const st
    int inet6_hash_connect(struct inet_timewait_death_row *death_row,
    struct sock *sk)
    {
    - u32 port_offset = 0;
    + u64 port_offset = 0;

    if (!inet_sk(sk)->inet_num)
    port_offset = inet6_sk_port_offset(sk);

    \
     
     \ /
      Last update: 2022-05-27 11:04    [W:4.025 / U:0.160 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site