aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-23 17:01:51 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-23 17:01:51 -0400
commit0cad43a7484179ec349e8e5792c558ee787a06ba (patch)
tree5e0931546c135c8802911ed2e5218c825b59ae2f
parentdf33db0f5efe8895203d221b9e701c0a61832c76 (diff)
parent7088ad74e6e710d0c80ea2cead9500f47a2a5d58 (diff)
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>
-rw-r--r--include/net/inet_frag.h4
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/ipv4/inet_fragment.c3
-rw-r--r--net/ipv4/ip_fragment.c1
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c16
-rw-r--r--net/ipv6/reassembly.c12
6 files changed, 25 insertions, 13 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index bfcbc0017950..6f59de98dabd 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -64,6 +64,10 @@ struct inet_frags {
64 rwlock_t lock ____cacheline_aligned_in_smp; 64 rwlock_t lock ____cacheline_aligned_in_smp;
65 int secret_interval; 65 int secret_interval;
66 struct timer_list secret_timer; 66 struct timer_list secret_timer;
67
68 /* The first call to hashfn is responsible to initialize
69 * rnd. This is best done with net_get_random_once.
70 */
67 u32 rnd; 71 u32 rnd;
68 int qsize; 72 int qsize;
69 73
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index a35055f4f8da..dd96638ab8ff 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -805,8 +805,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
805int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); 805int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
806int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, 806int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
807 struct group_filter __user *optval, int __user *optlen); 807 struct group_filter __user *optval, int __user *optlen);
808unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
809 const struct in6_addr *daddr, u32 rnd);
810 808
811#ifdef CONFIG_PROC_FS 809#ifdef CONFIG_PROC_FS
812int ac6_proc_init(struct net *net); 810int ac6_proc_init(struct net *net);
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index c5313a9c019b..bb075fc9a14f 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -93,9 +93,6 @@ void inet_frags_init(struct inet_frags *f)
93 } 93 }
94 rwlock_init(&f->lock); 94 rwlock_init(&f->lock);
95 95
96 f->rnd = (u32) ((totalram_pages ^ (totalram_pages >> 7)) ^
97 (jiffies ^ (jiffies >> 6)));
98
99 setup_timer(&f->secret_timer, inet_frag_secret_rebuild, 96 setup_timer(&f->secret_timer, inet_frag_secret_rebuild,
100 (unsigned long)f); 97 (unsigned long)f);
101 f->secret_timer.expires = jiffies + f->secret_interval; 98 f->secret_timer.expires = jiffies + f->secret_interval;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index b66910aaef4d..2481993a4970 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -106,6 +106,7 @@ struct ip4_create_arg {
106 106
107static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) 107static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
108{ 108{
109 net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd));
109 return jhash_3words((__force u32)id << 16 | prot, 110 return jhash_3words((__force u32)id << 16 | prot,
110 (__force u32)saddr, (__force u32)daddr, 111 (__force u32)saddr, (__force u32)daddr,
111 ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); 112 ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index dffdc1a389c5..4a258263d8ec 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -144,12 +144,24 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h)
144 return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK); 144 return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK);
145} 145}
146 146
147static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr,
148 const struct in6_addr *daddr)
149{
150 u32 c;
151
152 net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd));
153 c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
154 (__force u32)id, nf_frags.rnd);
155 return c & (INETFRAGS_HASHSZ - 1);
156}
157
158
147static unsigned int nf_hashfn(struct inet_frag_queue *q) 159static unsigned int nf_hashfn(struct inet_frag_queue *q)
148{ 160{
149 const struct frag_queue *nq; 161 const struct frag_queue *nq;
150 162
151 nq = container_of(q, struct frag_queue, q); 163 nq = container_of(q, struct frag_queue, q);
152 return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); 164 return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr);
153} 165}
154 166
155static void nf_skb_free(struct sk_buff *skb) 167static 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 arg.ecn = ecn; 197 arg.ecn = ecn;
186 198
187 read_lock_bh(&nf_frags.lock); 199 read_lock_bh(&nf_frags.lock);
188 hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); 200 hash = nf_hash_frag(id, src, dst);
189 201
190 q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); 202 q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
191 local_bh_enable(); 203 local_bh_enable();
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 1aeb473b2cc6..cc85a9ba5010 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -82,24 +82,24 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
82 * callers should be careful not to use the hash value outside the ipfrag_lock 82 * callers should be careful not to use the hash value outside the ipfrag_lock
83 * as doing so could race with ipfrag_hash_rnd being recalculated. 83 * as doing so could race with ipfrag_hash_rnd being recalculated.
84 */ 84 */
85unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, 85static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
86 const struct in6_addr *daddr, u32 rnd) 86 const struct in6_addr *daddr)
87{ 87{
88 u32 c; 88 u32 c;
89 89
90 net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd));
90 c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), 91 c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
91 (__force u32)id, rnd); 92 (__force u32)id, ip6_frags.rnd);
92 93
93 return c & (INETFRAGS_HASHSZ - 1); 94 return c & (INETFRAGS_HASHSZ - 1);
94} 95}
95EXPORT_SYMBOL_GPL(inet6_hash_frag);
96 96
97static unsigned int ip6_hashfn(struct inet_frag_queue *q) 97static unsigned int ip6_hashfn(struct inet_frag_queue *q)
98{ 98{
99 struct frag_queue *fq; 99 struct frag_queue *fq;
100 100
101 fq = container_of(q, struct frag_queue, q); 101 fq = container_of(q, struct frag_queue, q);
102 return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd); 102 return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr);
103} 103}
104 104
105bool ip6_frag_match(struct inet_frag_queue *q, void *a) 105bool 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 arg.ecn = ecn; 193 arg.ecn = ecn;
194 194
195 read_lock(&ip6_frags.lock); 195 read_lock(&ip6_frags.lock);
196 hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); 196 hash = inet6_hash_frag(id, src, dst);
197 197
198 q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); 198 q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
199 if (IS_ERR_OR_NULL(q)) { 199 if (IS_ERR_OR_NULL(q)) {