]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.20-nethashfix.patch
- added description of djurban's branch
[packages/kernel.git] / linux-2.4.20-nethashfix.patch
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 #
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  
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 #
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  
This page took 0.062089 seconds and 3 git commands to generate.