Commit 0cad43a7 authored by David S. Miller's avatar David S. Miller

Merge branch 'frag_hash_secret'

Hannes Frederic Sowa says:

====================
initialize fragment hash secrets with net_get_random_once

This series switches the inet_frag.rnd hash initialization to
net_get_random_once.

Included patches:
 ipv4: initialize ip4_frags hash secret as late
 ipv6: split inet6_hash_frag for netfilter and
 inet: remove old fragmentation hash initializing
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents df33db0f 7088ad74
...@@ -64,6 +64,10 @@ struct inet_frags { ...@@ -64,6 +64,10 @@ struct inet_frags {
rwlock_t lock ____cacheline_aligned_in_smp; rwlock_t lock ____cacheline_aligned_in_smp;
int secret_interval; int secret_interval;
struct timer_list secret_timer; struct timer_list secret_timer;
/* The first call to hashfn is responsible to initialize
* rnd. This is best done with net_get_random_once.
*/
u32 rnd; u32 rnd;
int qsize; int qsize;
......
...@@ -805,8 +805,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, ...@@ -805,8 +805,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
struct group_filter __user *optval, int __user *optlen); struct group_filter __user *optval, int __user *optlen);
unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
const struct in6_addr *daddr, u32 rnd);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
int ac6_proc_init(struct net *net); int ac6_proc_init(struct net *net);
......
...@@ -93,9 +93,6 @@ void inet_frags_init(struct inet_frags *f) ...@@ -93,9 +93,6 @@ void inet_frags_init(struct inet_frags *f)
} }
rwlock_init(&f->lock); rwlock_init(&f->lock);
f->rnd = (u32) ((totalram_pages ^ (totalram_pages >> 7)) ^
(jiffies ^ (jiffies >> 6)));
setup_timer(&f->secret_timer, inet_frag_secret_rebuild, setup_timer(&f->secret_timer, inet_frag_secret_rebuild,
(unsigned long)f); (unsigned long)f);
f->secret_timer.expires = jiffies + f->secret_interval; f->secret_timer.expires = jiffies + f->secret_interval;
......
...@@ -106,6 +106,7 @@ struct ip4_create_arg { ...@@ -106,6 +106,7 @@ struct ip4_create_arg {
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
{ {
net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd));
return jhash_3words((__force u32)id << 16 | prot, return jhash_3words((__force u32)id << 16 | prot,
(__force u32)saddr, (__force u32)daddr, (__force u32)saddr, (__force u32)daddr,
ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
......
...@@ -144,12 +144,24 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h) ...@@ -144,12 +144,24 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h)
return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK); return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK);
} }
static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr,
const struct in6_addr *daddr)
{
u32 c;
net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd));
c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
(__force u32)id, nf_frags.rnd);
return c & (INETFRAGS_HASHSZ - 1);
}
static unsigned int nf_hashfn(struct inet_frag_queue *q) static unsigned int nf_hashfn(struct inet_frag_queue *q)
{ {
const struct frag_queue *nq; const struct frag_queue *nq;
nq = container_of(q, struct frag_queue, q); nq = container_of(q, struct frag_queue, q);
return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr);
} }
static void nf_skb_free(struct sk_buff *skb) static void nf_skb_free(struct sk_buff *skb)
...@@ -185,7 +197,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, ...@@ -185,7 +197,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,
arg.ecn = ecn; arg.ecn = ecn;
read_lock_bh(&nf_frags.lock); read_lock_bh(&nf_frags.lock);
hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); hash = nf_hash_frag(id, src, dst);
q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
local_bh_enable(); local_bh_enable();
......
...@@ -82,24 +82,24 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, ...@@ -82,24 +82,24 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
* callers should be careful not to use the hash value outside the ipfrag_lock * callers should be careful not to use the hash value outside the ipfrag_lock
* as doing so could race with ipfrag_hash_rnd being recalculated. * as doing so could race with ipfrag_hash_rnd being recalculated.
*/ */
unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
const struct in6_addr *daddr, u32 rnd) const struct in6_addr *daddr)
{ {
u32 c; u32 c;
net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd));
c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
(__force u32)id, rnd); (__force u32)id, ip6_frags.rnd);
return c & (INETFRAGS_HASHSZ - 1); return c & (INETFRAGS_HASHSZ - 1);
} }
EXPORT_SYMBOL_GPL(inet6_hash_frag);
static unsigned int ip6_hashfn(struct inet_frag_queue *q) static unsigned int ip6_hashfn(struct inet_frag_queue *q)
{ {
struct frag_queue *fq; struct frag_queue *fq;
fq = container_of(q, struct frag_queue, q); fq = container_of(q, struct frag_queue, q);
return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd); return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr);
} }
bool ip6_frag_match(struct inet_frag_queue *q, void *a) bool ip6_frag_match(struct inet_frag_queue *q, void *a)
...@@ -193,7 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, ...@@ -193,7 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src,
arg.ecn = ecn; arg.ecn = ecn;
read_lock(&ip6_frags.lock); read_lock(&ip6_frags.lock);
hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); hash = inet6_hash_frag(id, src, dst);
q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
if (IS_ERR_OR_NULL(q)) { if (IS_ERR_OR_NULL(q)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment