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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0cad43a748
@ -64,6 +64,10 @@ struct inet_frags {
|
||||
rwlock_t lock ____cacheline_aligned_in_smp;
|
||||
int secret_interval;
|
||||
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;
|
||||
int qsize;
|
||||
|
||||
|
@ -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_msfget(struct sock *sk, struct group_filter *gsf,
|
||||
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
|
||||
int ac6_proc_init(struct net *net);
|
||||
|
@ -93,9 +93,6 @@ void inet_frags_init(struct inet_frags *f)
|
||||
}
|
||||
rwlock_init(&f->lock);
|
||||
|
||||
f->rnd = (u32) ((totalram_pages ^ (totalram_pages >> 7)) ^
|
||||
(jiffies ^ (jiffies >> 6)));
|
||||
|
||||
setup_timer(&f->secret_timer, inet_frag_secret_rebuild,
|
||||
(unsigned long)f);
|
||||
f->secret_timer.expires = jiffies + f->secret_interval;
|
||||
|
@ -106,6 +106,7 @@ struct ip4_create_arg {
|
||||
|
||||
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,
|
||||
(__force u32)saddr, (__force u32)daddr,
|
||||
ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
|
||||
|
@ -144,12 +144,24 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h)
|
||||
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)
|
||||
{
|
||||
const struct frag_queue *nq;
|
||||
|
||||
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)
|
||||
@ -185,7 +197,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,
|
||||
arg.ecn = ecn;
|
||||
|
||||
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);
|
||||
local_bh_enable();
|
||||
|
@ -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
|
||||
* as doing so could race with ipfrag_hash_rnd being recalculated.
|
||||
*/
|
||||
unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
|
||||
const struct in6_addr *daddr, u32 rnd)
|
||||
static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
|
||||
const struct in6_addr *daddr)
|
||||
{
|
||||
u32 c;
|
||||
|
||||
net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd));
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inet6_hash_frag);
|
||||
|
||||
static unsigned int ip6_hashfn(struct inet_frag_queue *q)
|
||||
{
|
||||
struct frag_queue *fq;
|
||||
|
||||
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)
|
||||
@ -193,7 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src,
|
||||
arg.ecn = ecn;
|
||||
|
||||
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);
|
||||
if (IS_ERR_OR_NULL(q)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user