]>
Commit | Line | Data |
---|---|---|
e6ffc12d JB |
1 | # This is a BitKeeper generated patch for the following project: |
2 | # Project Name: Linux kernel tree | |
3 | # This patch format is intended for GNU patch command version 2.5 or higher. | |
4 | # This patch includes the following deltas: | |
5 | # ChangeSet 1.1142 -> 1.1143 | |
6 | # net/ipv4/netfilter/ip_conntrack_core.c 1.17 -> 1.18 | |
7 | # include/linux/sysctl.h 1.22 -> 1.23 | |
8 | # net/ipv6/tcp_ipv6.c 1.21 -> 1.22 | |
9 | # include/net/tcp.h 1.21 -> 1.22 | |
10 | # net/ipv4/tcp.c 1.25 -> 1.26 | |
11 | # net/ipv4/tcp_ipv4.c 1.20 -> 1.21 | |
12 | # net/ipv4/route.c 1.21 -> 1.22 | |
13 | # (new) -> 1.1 include/linux/jhash.h | |
14 | # | |
15 | # The following is the BitKeeper ChangeSet Log | |
16 | # -------------------------------------------- | |
17 | # 03/05/03 davem@nuts.ninka.net 1.1143 | |
18 | # [NET]: Fix hashing exploits in ipv4 routing, IP conntrack, and TCP synq. | |
19 | # | |
20 | # Several hash table implementations in the networking were | |
21 | # remotely exploitable. Remote attackers could launch attacks | |
22 | # whereby, using carefully choosen forged source addresses, make | |
23 | # every routing cache entry get hashed into the same hash chain. | |
24 | # | |
25 | # Netfilter's IP conntrack module and the TCP syn-queue implementation | |
26 | # had identical vulnerabilities and have been fixed too. | |
27 | # | |
28 | # The choosen solution to the problem involved using Bob's Jenkins | |
29 | # hash along with a randomly choosen input. For the ipv4 routing | |
30 | # cache we take things one step further and periodically choose a | |
31 | # new random secret. By default this happens every 10 minutes, but | |
32 | # this is configurable by the user via sysctl knobs. | |
33 | # -------------------------------------------- | |
34 | # | |
e6ffc12d JB |
35 | diff -Nru a/include/net/tcp.h b/include/net/tcp.h |
36 | --- a/include/net/tcp.h Tue May 6 02:39:57 2003 | |
37 | +++ b/include/net/tcp.h Tue May 6 02:39:57 2003 | |
38 | @@ -1604,6 +1604,7 @@ | |
39 | int qlen; | |
40 | int qlen_young; | |
41 | int clock_hand; | |
42 | + u32 hash_rnd; | |
43 | struct open_request *syn_table[TCP_SYNQ_HSIZE]; | |
44 | }; | |
45 | ||
e6ffc12d JB |
46 | diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c |
47 | --- a/net/ipv4/route.c Tue May 6 02:39:57 2003 | |
48 | +++ b/net/ipv4/route.c Tue May 6 02:39:57 2003 | |
49 | @@ -85,6 +85,7 @@ | |
50 | #include <linux/mroute.h> | |
51 | #include <linux/netfilter_ipv4.h> | |
52 | #include <linux/random.h> | |
53 | +#include <linux/jhash.h> | |
54 | #include <net/protocol.h> | |
55 | #include <net/ip.h> | |
56 | #include <net/route.h> | |
57 | @@ -117,13 +118,14 @@ | |
58 | int ip_rt_mtu_expires = 10 * 60 * HZ; | |
59 | int ip_rt_min_pmtu = 512 + 20 + 20; | |
60 | int ip_rt_min_advmss = 256; | |
61 | - | |
62 | +int ip_rt_secret_interval = 10 * 60 * HZ; | |
63 | static unsigned long rt_deadline; | |
64 | ||
65 | #define RTprint(a...) printk(KERN_DEBUG a) | |
66 | ||
67 | static struct timer_list rt_flush_timer; | |
68 | static struct timer_list rt_periodic_timer; | |
69 | +static struct timer_list rt_secret_timer; | |
70 | ||
71 | /* | |
72 | * Interface to generic destination cache. | |
73 | @@ -194,19 +196,17 @@ | |
74 | static struct rt_hash_bucket *rt_hash_table; | |
75 | static unsigned rt_hash_mask; | |
76 | static int rt_hash_log; | |
77 | +static unsigned int rt_hash_rnd; | |
78 | ||
79 | struct rt_cache_stat rt_cache_stat[NR_CPUS]; | |
80 | ||
81 | static int rt_intern_hash(unsigned hash, struct rtable *rth, | |
82 | struct rtable **res); | |
83 | ||
84 | -static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos) | |
85 | +static unsigned int rt_hash_code(u32 daddr, u32 saddr, u8 tos) | |
86 | { | |
87 | - unsigned hash = ((daddr & 0xF0F0F0F0) >> 4) | | |
88 | - ((daddr & 0x0F0F0F0F) << 4); | |
89 | - hash ^= saddr ^ tos; | |
90 | - hash ^= (hash >> 16); | |
91 | - return (hash ^ (hash >> 8)) & rt_hash_mask; | |
92 | + return (jenkins_hash_3words(daddr, saddr, (u32) tos, rt_hash_rnd) | |
93 | + & rt_hash_mask); | |
94 | } | |
95 | ||
96 | static int rt_cache_get_info(char *buffer, char **start, off_t offset, | |
97 | @@ -479,6 +479,15 @@ | |
98 | spin_unlock_bh(&rt_flush_lock); | |
99 | } | |
100 | ||
101 | +static void rt_secret_rebuild(unsigned long dummy) | |
102 | +{ | |
103 | + unsigned long now = jiffies; | |
104 | + | |
105 | + get_random_bytes(&rt_hash_rnd, 4); | |
106 | + rt_cache_flush(0); | |
107 | + mod_timer(&rt_secret_timer, now + ip_rt_secret_interval); | |
108 | +} | |
109 | + | |
110 | /* | |
111 | Short description of GC goals. | |
112 | ||
113 | @@ -2414,6 +2423,15 @@ | |
114 | mode: 0644, | |
115 | proc_handler: &proc_dointvec, | |
116 | }, | |
117 | + { | |
118 | + ctl_name: NET_IPV4_ROUTE_SECRET_INTERVAL, | |
119 | + procname: "secret_interval", | |
120 | + data: &ip_rt_secret_interval, | |
121 | + maxlen: sizeof(int), | |
122 | + mode: 0644, | |
123 | + proc_handler: &proc_dointvec_jiffies, | |
124 | + strategy: &sysctl_jiffies, | |
125 | + }, | |
126 | { 0 } | |
127 | }; | |
128 | #endif | |
129 | @@ -2444,15 +2462,25 @@ | |
130 | *eof = 1; | |
131 | } | |
132 | ||
133 | - /* Copy first cpu. */ | |
134 | - *start = buffer; | |
135 | - memcpy(buffer, IP_RT_ACCT_CPU(0), length); | |
136 | - | |
137 | - /* Add the other cpus in, one int at a time */ | |
138 | - for (i = 1; i < smp_num_cpus; i++) { | |
139 | - unsigned int j; | |
140 | - for (j = 0; j < length/4; j++) | |
141 | - ((u32*)buffer)[j] += ((u32*)IP_RT_ACCT_CPU(i))[j]; | |
142 | + offset /= sizeof(u32); | |
143 | + | |
144 | + if (length > 0) { | |
145 | + u32 *src = ((u32 *) IP_RT_ACCT_CPU(0)) + offset; | |
146 | + u32 *dst = (u32 *) buffer; | |
147 | + | |
148 | + /* Copy first cpu. */ | |
149 | + *start = buffer; | |
150 | + memcpy(dst, src, length); | |
151 | + | |
152 | + /* Add the other cpus in, one int at a time */ | |
153 | + for (i = 1; i < smp_num_cpus; i++) { | |
154 | + unsigned int j; | |
155 | + | |
156 | + src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset; | |
157 | + | |
158 | + for (j = 0; j < length/4; j++) | |
159 | + dst[j] += src[j]; | |
160 | + } | |
161 | } | |
162 | return length; | |
163 | } | |
164 | @@ -2462,6 +2490,9 @@ | |
165 | { | |
166 | int i, order, goal; | |
167 | ||
168 | + rt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^ | |
169 | + (jiffies ^ (jiffies >> 7))); | |
170 | + | |
171 | #ifdef CONFIG_NET_CLS_ROUTE | |
172 | for (order = 0; | |
173 | (PAGE_SIZE << order) < 256 * sizeof(struct ip_rt_acct) * NR_CPUS; order++) | |
174 | @@ -2518,6 +2549,7 @@ | |
175 | ||
176 | rt_flush_timer.function = rt_run_flush; | |
177 | rt_periodic_timer.function = rt_check_expire; | |
178 | + rt_secret_timer.function = rt_secret_rebuild; | |
179 | ||
180 | /* All the timers, started at system startup tend | |
181 | to synchronize. Perturb it a bit. | |
182 | @@ -2525,6 +2557,10 @@ | |
183 | rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval + | |
184 | ip_rt_gc_interval; | |
185 | add_timer(&rt_periodic_timer); | |
186 | + | |
187 | + rt_secret_timer.expires = jiffies + net_random() % ip_rt_secret_interval + | |
188 | + ip_rt_secret_interval; | |
189 | + add_timer(&rt_secret_timer); | |
190 | ||
191 | proc_net_create ("rt_cache", 0, rt_cache_get_info); | |
192 | proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info); | |
193 | diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c | |
194 | --- a/net/ipv4/tcp.c Tue May 6 02:39:57 2003 | |
195 | +++ b/net/ipv4/tcp.c Tue May 6 02:39:57 2003 | |
196 | @@ -252,6 +252,7 @@ | |
197 | #include <linux/init.h> | |
198 | #include <linux/smp_lock.h> | |
199 | #include <linux/fs.h> | |
200 | +#include <linux/random.h> | |
201 | ||
202 | #include <net/icmp.h> | |
203 | #include <net/tcp.h> | |
204 | @@ -542,6 +543,7 @@ | |
205 | for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++) | |
206 | if ((1<<lopt->max_qlen_log) >= sysctl_max_syn_backlog) | |
207 | break; | |
208 | + get_random_bytes(&lopt->hash_rnd, 4); | |
209 | ||
210 | write_lock_bh(&tp->syn_wait_lock); | |
211 | tp->listen_opt = lopt; | |
212 | diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c | |
213 | --- a/net/ipv4/tcp_ipv4.c Tue May 6 02:39:57 2003 | |
214 | +++ b/net/ipv4/tcp_ipv4.c Tue May 6 02:39:57 2003 | |
215 | @@ -56,6 +56,7 @@ | |
216 | #include <linux/fcntl.h> | |
217 | #include <linux/random.h> | |
218 | #include <linux/cache.h> | |
219 | +#include <linux/jhash.h> | |
220 | #include <linux/init.h> | |
221 | ||
222 | #include <net/icmp.h> | |
223 | @@ -868,12 +869,10 @@ | |
224 | return ((struct rtable*)skb->dst)->rt_iif; | |
225 | } | |
226 | ||
227 | -static __inline__ unsigned tcp_v4_synq_hash(u32 raddr, u16 rport) | |
228 | +static __inline__ u32 tcp_v4_synq_hash(u32 raddr, u16 rport, u32 rnd) | |
229 | { | |
230 | - unsigned h = raddr ^ rport; | |
231 | - h ^= h>>16; | |
232 | - h ^= h>>8; | |
233 | - return h&(TCP_SYNQ_HSIZE-1); | |
234 | + return (jenkins_hash_2words(raddr, (u32) rport, rnd) | |
235 | + & (TCP_SYNQ_HSIZE - 1)); | |
236 | } | |
237 | ||
238 | static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, | |
239 | @@ -884,7 +883,7 @@ | |
240 | struct tcp_listen_opt *lopt = tp->listen_opt; | |
241 | struct open_request *req, **prev; | |
242 | ||
243 | - for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport)]; | |
244 | + for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)]; | |
245 | (req = *prev) != NULL; | |
246 | prev = &req->dl_next) { | |
247 | if (req->rmt_port == rport && | |
248 | @@ -904,7 +903,7 @@ | |
249 | { | |
250 | struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; | |
251 | struct tcp_listen_opt *lopt = tp->listen_opt; | |
252 | - unsigned h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port); | |
253 | + u32 h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port, lopt->hash_rnd); | |
254 | ||
255 | req->expires = jiffies + TCP_TIMEOUT_INIT; | |
256 | req->retrans = 0; | |
257 | diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c | |
258 | --- a/net/ipv6/tcp_ipv6.c Tue May 6 02:39:57 2003 | |
259 | +++ b/net/ipv6/tcp_ipv6.c Tue May 6 02:39:57 2003 | |
260 | @@ -36,6 +36,7 @@ | |
261 | #include <linux/in6.h> | |
262 | #include <linux/netdevice.h> | |
263 | #include <linux/init.h> | |
264 | +#include <linux/jhash.h> | |
265 | #include <linux/ipsec.h> | |
266 | ||
267 | #include <linux/ipv6.h> | |
268 | @@ -368,12 +369,12 @@ | |
269 | * Open request hash tables. | |
270 | */ | |
271 | ||
272 | -static __inline__ unsigned tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport) | |
273 | +static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd) | |
274 | { | |
275 | - unsigned h = raddr->s6_addr32[3] ^ rport; | |
276 | - h ^= h>>16; | |
277 | - h ^= h>>8; | |
278 | - return h&(TCP_SYNQ_HSIZE-1); | |
279 | + return (jenkins_hash_3words(raddr->s6_addr32[0] ^ raddr->s6_addr32[1], | |
280 | + raddr->s6_addr32[2] ^ raddr->s6_addr32[3], | |
281 | + (u32) rport, rnd) | |
282 | + & (TCP_SYNQ_HSIZE - 1)); | |
283 | } | |
284 | ||
285 | static struct open_request *tcp_v6_search_req(struct tcp_opt *tp, | |
286 | @@ -386,7 +387,7 @@ | |
287 | struct tcp_listen_opt *lopt = tp->listen_opt; | |
288 | struct open_request *req, **prev; | |
289 | ||
290 | - for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport)]; | |
291 | + for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)]; | |
292 | (req = *prev) != NULL; | |
293 | prev = &req->dl_next) { | |
294 | if (req->rmt_port == rport && | |
295 | @@ -1135,7 +1136,7 @@ | |
296 | { | |
297 | struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; | |
298 | struct tcp_listen_opt *lopt = tp->listen_opt; | |
299 | - unsigned h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port); | |
300 | + u32 h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port, lopt->hash_rnd); | |
301 | ||
302 | req->sk = NULL; | |
303 | req->expires = jiffies + TCP_TIMEOUT_INIT; | |
304 | # This is a BitKeeper generated patch for the following project: | |
305 | # Project Name: Linux kernel tree | |
306 | # This patch format is intended for GNU patch command version 2.5 or higher. | |
307 | # This patch includes the following deltas: | |
308 | # ChangeSet 1.1144 -> 1.1145 | |
309 | # net/ipv4/netfilter/ip_conntrack_core.c 1.18 -> 1.19 | |
310 | # net/ipv6/tcp_ipv6.c 1.22 -> 1.23 | |
311 | # net/ipv4/tcp_ipv4.c 1.21 -> 1.22 | |
312 | # include/linux/jhash.h 1.1 -> 1.2 | |
313 | # net/ipv4/route.c 1.22 -> 1.23 | |
314 | # | |
315 | # The following is the BitKeeper ChangeSet Log | |
316 | # -------------------------------------------- | |
317 | # 03/05/03 jmorris@intercode.com.au 1.1145 | |
318 | # [NET]: Cosmetic cleanups of jhash code. | |
319 | # - Consistent naming (i.e. jhash_xxx) | |
320 | # - Reduces the 2&1 word variants to call jhash_3words() | |
321 | # - Replaces __inline__ with inline. | |
322 | # -------------------------------------------- | |
323 | # | |
e6ffc12d JB |
324 | diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c |
325 | --- a/net/ipv4/route.c Tue May 6 02:40:04 2003 | |
326 | +++ b/net/ipv4/route.c Tue May 6 02:40:04 2003 | |
327 | @@ -205,7 +205,7 @@ | |
328 | ||
329 | static unsigned int rt_hash_code(u32 daddr, u32 saddr, u8 tos) | |
330 | { | |
331 | - return (jenkins_hash_3words(daddr, saddr, (u32) tos, rt_hash_rnd) | |
332 | + return (jhash_3words(daddr, saddr, (u32) tos, rt_hash_rnd) | |
333 | & rt_hash_mask); | |
334 | } | |
335 | ||
336 | diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c | |
337 | --- a/net/ipv4/tcp_ipv4.c Tue May 6 02:40:04 2003 | |
338 | +++ b/net/ipv4/tcp_ipv4.c Tue May 6 02:40:04 2003 | |
339 | @@ -871,8 +871,7 @@ | |
340 | ||
341 | static __inline__ u32 tcp_v4_synq_hash(u32 raddr, u16 rport, u32 rnd) | |
342 | { | |
343 | - return (jenkins_hash_2words(raddr, (u32) rport, rnd) | |
344 | - & (TCP_SYNQ_HSIZE - 1)); | |
345 | + return (jhash_2words(raddr, (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1)); | |
346 | } | |
347 | ||
348 | static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, | |
349 | diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c | |
350 | --- a/net/ipv6/tcp_ipv6.c Tue May 6 02:40:04 2003 | |
351 | +++ b/net/ipv6/tcp_ipv6.c Tue May 6 02:40:04 2003 | |
352 | @@ -371,10 +371,9 @@ | |
353 | ||
354 | static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd) | |
355 | { | |
356 | - return (jenkins_hash_3words(raddr->s6_addr32[0] ^ raddr->s6_addr32[1], | |
357 | - raddr->s6_addr32[2] ^ raddr->s6_addr32[3], | |
358 | - (u32) rport, rnd) | |
359 | - & (TCP_SYNQ_HSIZE - 1)); | |
360 | + return (jhash_3words(raddr->s6_addr32[0] ^ raddr->s6_addr32[1], | |
361 | + raddr->s6_addr32[2] ^ raddr->s6_addr32[3], | |
362 | + (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1)); | |
363 | } | |
364 | ||
365 | static struct open_request *tcp_v6_search_req(struct tcp_opt *tp, | |
366 | # This is a BitKeeper generated patch for the following project: | |
367 | # Project Name: Linux kernel tree | |
368 | # This patch format is intended for GNU patch command version 2.5 or higher. | |
369 | # This patch includes the following deltas: | |
370 | # ChangeSet 1.1145 -> 1.1146 | |
371 | # net/ipv4/route.c 1.23 -> 1.24 | |
372 | # | |
373 | # The following is the BitKeeper ChangeSet Log | |
374 | # -------------------------------------------- | |
375 | # 03/05/04 jmorris@intercode.com.au 1.1146 | |
376 | # [IPV4]: Choose new rt_hash_rnd every rt_run_flush. | |
377 | # -------------------------------------------- | |
378 | # | |
379 | diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c | |
380 | --- a/net/ipv4/route.c Tue May 6 02:40:09 2003 | |
381 | +++ b/net/ipv4/route.c Tue May 6 02:40:09 2003 | |
382 | @@ -421,6 +421,8 @@ | |
383 | ||
384 | rt_deadline = 0; | |
385 | ||
386 | + get_random_bytes(&rt_hash_rnd, 4); | |
387 | + | |
388 | for (i = rt_hash_mask; i >= 0; i--) { | |
389 | write_lock_bh(&rt_hash_table[i].lock); | |
390 | rth = rt_hash_table[i].chain; | |
391 | @@ -483,7 +485,6 @@ | |
392 | { | |
393 | unsigned long now = jiffies; | |
394 | ||
395 | - get_random_bytes(&rt_hash_rnd, 4); | |
396 | rt_cache_flush(0); | |
397 | mod_timer(&rt_secret_timer, now + ip_rt_secret_interval); | |
398 | } | |
399 | # This is a BitKeeper generated patch for the following project: | |
400 | # Project Name: Linux kernel tree | |
401 | # This patch format is intended for GNU patch command version 2.5 or higher. | |
402 | # This patch includes the following deltas: | |
403 | # ChangeSet 1.1094 -> 1.1095 | |
404 | # net/ipv4/tcp_minisocks.c 1.27 -> 1.28 | |
405 | # | |
406 | # The following is the BitKeeper ChangeSet Log | |
407 | # -------------------------------------------- | |
408 | # 03/05/07 olof@austin.ibm.com 1.1095 | |
409 | # [TCP]: tcp_twkill leaves death row list in inconsistent state over tcp_timewait_kill. | |
410 | # -------------------------------------------- | |
411 | # | |
412 | diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c | |
413 | --- a/net/ipv4/tcp_minisocks.c Wed May 7 02:29:49 2003 | |
414 | +++ b/net/ipv4/tcp_minisocks.c Wed May 7 02:29:49 2003 | |
415 | @@ -444,6 +444,8 @@ | |
416 | ||
417 | while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) { | |
418 | tcp_tw_death_row[tcp_tw_death_row_slot] = tw->next_death; | |
419 | + if (tw->next_death) | |
420 | + tw->next_death->pprev_death = tw->pprev_death; | |
421 | tw->pprev_death = NULL; | |
422 | spin_unlock(&tw_death_lock); | |
423 |