Skip to content

Commit

Permalink
[INET]: Use jhash + random secret for ehash.
Browse files Browse the repository at this point in the history
The days are gone when this was not an issue, there are folks out
there with huge bot networks that can be used to attack the
established hash tables on remote systems.

So just like the routing cache and connection tracking
hash, use Jenkins hash with random secret input.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller authored and David S. Miller committed Apr 26, 2007
1 parent d30045a commit b3da2cf
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 9 deletions.
12 changes: 7 additions & 5 deletions include/net/inet6_hashtables.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include <linux/in6.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <linux/jhash.h>

#include <net/inet_sock.h>

#include <net/ipv6.h>

Expand All @@ -28,12 +31,11 @@ struct inet_hashinfo;
static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
const struct in6_addr *faddr, const __be16 fport)
{
unsigned int hashent = (lport ^ (__force u16)fport);
u32 ports = (lport ^ (__force u16)fport);

hashent ^= (__force u32)(laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
hashent ^= hashent >> 16;
hashent ^= hashent >> 8;
return hashent;
return jhash_3words((__force u32)laddr->s6_addr32[3],
(__force u32)faddr->s6_addr32[3],
ports, inet_ehash_secret);
}

static inline int inet6_sk_ehashfn(const struct sock *sk)
Expand Down
11 changes: 7 additions & 4 deletions include/net/inet_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <linux/string.h>
#include <linux/types.h>
#include <linux/jhash.h>

#include <net/flow.h>
#include <net/sock.h>
Expand Down Expand Up @@ -167,13 +168,15 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,

extern int inet_sk_rebuild_header(struct sock *sk);

extern u32 inet_ehash_secret;
extern void build_ehash_secret(void);

static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
const __be32 faddr, const __be16 fport)
{
unsigned int h = ((__force __u32)laddr ^ lport) ^ ((__force __u32)faddr ^ (__force __u32)fport);
h ^= h >> 16;
h ^= h >> 8;
return h;
return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr,
((__u32) lport) << 16 | (__force __u32)fport,
inet_ehash_secret);
}

static inline int inet_sk_ehashfn(const struct sock *sk)
Expand Down
16 changes: 16 additions & 0 deletions net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/netfilter_ipv4.h>
#include <linux/random.h>

#include <asm/uaccess.h>
#include <asm/system.h>
Expand Down Expand Up @@ -217,6 +218,16 @@ int inet_listen(struct socket *sock, int backlog)
return err;
}

u32 inet_ehash_secret;
EXPORT_SYMBOL(inet_ehash_secret);

void build_ehash_secret(void)
{
while (!inet_ehash_secret)
get_random_bytes(&inet_ehash_secret, 4);
}
EXPORT_SYMBOL(build_ehash_secret);

/*
* Create an inet socket.
*/
Expand All @@ -233,6 +244,11 @@ static int inet_create(struct socket *sock, int protocol)
int try_loading_module = 0;
int err;

if (sock->type != SOCK_RAW &&
sock->type != SOCK_DGRAM &&
!inet_ehash_secret)
build_ehash_secret();

sock->state = SS_UNCONNECTED;

/* Look for the requested type/protocol pair. */
Expand Down
5 changes: 5 additions & 0 deletions net/ipv6/af_inet6.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ static int inet6_create(struct socket *sock, int protocol)
int try_loading_module = 0;
int err;

if (sock->type != SOCK_RAW &&
sock->type != SOCK_DGRAM &&
!inet_ehash_secret)
build_ehash_secret();

/* Look for the requested type/protocol pair. */
answer = NULL;
lookup_protocol:
Expand Down

0 comments on commit b3da2cf

Please sign in to comment.