diff options
author | David S. Miller <davem@davemloft.net> | 2013-10-23 17:01:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-23 17:01:51 -0400 |
commit | 0cad43a7484179ec349e8e5792c558ee787a06ba (patch) | |
tree | 5e0931546c135c8802911ed2e5218c825b59ae2f | |
parent | df33db0f5efe8895203d221b9e701c0a61832c76 (diff) | |
parent | 7088ad74e6e710d0c80ea2cead9500f47a2a5d58 (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.h | 4 | ||||
-rw-r--r-- | include/net/ipv6.h | 2 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 16 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 12 |
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, | |||
805 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); | 805 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); |
806 | int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | 806 | int 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); |
808 | unsigned 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 |
812 | int ac6_proc_init(struct net *net); | 810 | int 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 | ||
107 | static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) | 107 | static 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 | ||
147 | static 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 | |||
147 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 159 | static 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 | ||
155 | static void nf_skb_free(struct sk_buff *skb) | 167 | 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 | 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 | */ |
85 | unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, | 85 | static 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 | } |
95 | EXPORT_SYMBOL_GPL(inet6_hash_frag); | ||
96 | 96 | ||
97 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) | 97 | static 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 | ||
105 | bool ip6_frag_match(struct inet_frag_queue *q, void *a) | 105 | 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 | 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)) { |