Package: kernel-image-2.6.8-11-amd64-k8-smp
Severity: important

While using the ipt_recent kernel module to stop SSH bruteforce attacks,
the kernel panics on a 32-bitism.  This crash can occur at any time.

-------------------8<-----------------------
Unable to handle kernel paging request at ffffff00005e3000 RIP:                 
          
<ffffffff801c8a20>{__memset+32}                                 
PML4 3e8063 PGD 1ff9067 PMD 365ae067 PTE 0
Oops: 0002 [1] SMP                        
CPU 0              
Modules linked in: ipv6 ipt_REJECT ipt_LOG ipt_state ipt_pkttype ipt_recent 
ipt_iprange ipt
Pid: 0, comm: swapper Not tainted 2.6.8-11-amd64-k8-smp                         
          
RIP: 0010:[<ffffffff801c8a20>] <ffffffff801c8a20>{__memset+32}
RSP: 0018:ffffffff80392450  EFLAGS: 00010216                  
RAX: 0000000000000000 RBX: 00000000000007f8 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffff00005e3000
RBP: ffffff00005dd000 R08: 0000000000000000 R09: ffffff00005e2fe0
R10: ffffff00005e4000 R11: ffffff00005e6000 R12: 0000000000000059
R13: ffffff00005df000 R14: 000000008b905486 R15: 0000000000000059
FS:  0000002a958ab640(0000) GS:ffffffff803e2e40(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b                           
CR2: ffffff00005e3000 CR3: 0000000000101000 CR4: 00000000000006e0
Process swapper (pid: 0, threadinfo ffffffff803e6000, task ffffffff802ef6c0)
Stack: ffffffffa01f38f0 ffffffffa01a4f1d ffffff00005e6000 ffffff00005e4000  
       0000000000000206 ffffffff7ec35980 40ffff0000000059 ffffff00005f2418 
       00000001005be582 00000000803925d0                                   
Call Trace:<IRQ> <ffffffffa01f38f0>{:ipt_recent:match+1728} 
<ffffffffa01a4f1d>{:ip_conntra 
       <ffffffffa019c28d>{:ip_tables:ipt_do_table+605} 
<ffffffff8024e91a>{nf_iterate+90}  
       <ffffffff8025ed50>{ip_local_deliver_finish+0} 
<ffffffff8024ed87>{nf_hook_slow+135} 
       <ffffffff8025ed50>{ip_local_deliver_finish+0} 
<ffffffff8025f160>{ip_local_deliver+5 
       <ffffffff8025f3b3>{ip_rcv_finish+579} 
<ffffffff8025f170>{ip_rcv_finish+0}          
       <ffffffff8025f170>{ip_rcv_finish+0} <ffffffff8024edca>{nf_hook_slow+202} 
 
       <ffffffff8025f170>{ip_rcv_finish+0} <ffffffff8025f89d>{ip_rcv+1165}      
       <ffffffff80245f1d>{netif_receive_skb+461} 
<ffffffff8010fbd5>{ret_from_intr+0} 
       <ffffffffa00f73b9>{:tg3:tg3_poll+1705} 
<ffffffff80246114>{net_rx_action+132}  
       <ffffffff801391e3>{__do_softirq+83} <ffffffff80139275>{do_softirq+53}    
    
       <ffffffff801125a1>{do_IRQ+321} <ffffffff8010d980>{default_idle+0}     
       <ffffffff8010fbd5>{ret_from_intr+0}  <EOI> 
<ffffffff802a5399>{thread_return+41} 
       <ffffffff8010d9a0>{default_idle+32} <ffffffff8010da2a>{cpu_idle+26}      
       
       <ffffffff803e96fb>{start_kernel+507} <ffffffff803e9203>{_sinittext+515} 
                                                                               
       
Code: f3 48 ab 44 89 c1 f3 aa 4c 89 c8 c3 66 66 66 90 ff c9 48 89 
RIP <ffffffff801c8a20>{__memset+32} RSP <ffffffff80392450>        
CR2: ffffff00005e3000                                     
 <0>Kernel panic: Aiee, killing interrupt handler!
In interrupt handler - not syncing                
 <0>Rebooting in 30 seconds..     
-------------------8<-----------------------

The blog entry below details the bug and supplies the patch:

    http://blog.blackdown.de/2005/05/09/fixing-the-ipt_recent-netfilter-module/
    http://blog.blackdown.de/static/kernel/ipt_recent-fix.patch

Here is the patch for 2.6:

-------------------8<-----------------------
Fixing the ipt_recent Netfilter Module
(cf. 
http://blog.blackdown.de/2005/05/09/fixing-the-ipt_recent-netfilter-module/)

I've had some ipt_recent rules acting strangely after an uptime of
about 25 days.  The problem is reproducible in the 5 minutes before
the first jiffies roll-over right after booting too.

The problem is caused by the jiffies comparision which doesn't work
like intended if one of the last hit was more than LONG_MAX seconds
again or if the table of last hits contains empty slots and jiffies
is > LONG_MAX.

This patch fixes the problem by using get_seconds() instead of
jiffies.  It also fixes some 64-bit issues.


Signed-off-by: Juergen Kreileder <[EMAIL PROTECTED]>

diff --exclude=arch --exclude-from=Documentation/dontdiff -ur 
../linux-2.6.12-rc3-mm3/include/linux/netfilter_ipv4/ipt_recent.h 
./include/linux/netfilter_ipv4/ipt_recent.h
--- ../linux-2.6.12-rc3-mm3/include/linux/netfilter_ipv4/ipt_recent.h   
2005-03-02 08:38:10.000000000 +0100
+++ ./include/linux/netfilter_ipv4/ipt_recent.h 2005-05-09 14:50:40.000000000 
+0200
@@ -2,7 +2,7 @@
 #define _IPT_RECENT_H
 
 #define RECENT_NAME    "ipt_recent"
-#define RECENT_VER     "v0.3.1"
+#define RECENT_VER     "v0.3.2"
 
 #define IPT_RECENT_CHECK  1
 #define IPT_RECENT_SET    2
diff --exclude=arch --exclude-from=Documentation/dontdiff -ur 
../linux-2.6.12-rc3-mm3/net/ipv4/netfilter/ipt_recent.c 
./net/ipv4/netfilter/ipt_recent.c
--- ../linux-2.6.12-rc3-mm3/net/ipv4/netfilter/ipt_recent.c     2005-03-02 
08:37:48.000000000 +0100
+++ ./net/ipv4/netfilter/ipt_recent.c   2005-05-09 15:06:58.000000000 +0200
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 #include <linux/ip.h>
 #include <linux/vmalloc.h>
+#include <linux/time.h>
 #include <linux/moduleparam.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
@@ -64,7 +65,7 @@
 
 struct time_info_list {
        u_int32_t position;
-       u_int32_t time;
+       unsigned long time;
 };
 
 /* Structure of our linked list of tables of recent lists. */
@@ -223,7 +224,7 @@
                        curr_table->table[count].last_seen = 0;
                        curr_table->table[count].addr = 0;
                        curr_table->table[count].ttl = 0;
-                       
memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+                       
memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned 
long));
                        curr_table->table[count].oldest_pkt = 0;
                        curr_table->table[count].time_pos = 0;
                        curr_table->time_info[count].position = count;
@@ -418,8 +419,8 @@
        if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, 
addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);
 #endif
 
-       /* Get jiffies now in case they changed while we were waiting for a 
lock */
-       now = jiffies;
+       /* Get time now in case it changed while we were waiting for a lock */
+       now = get_seconds();
        hash_table = curr_table->hash_table;
        time_info = curr_table->time_info;
 
@@ -502,7 +503,7 @@
                location = time_info[curr_table->time_pos].position;
                hash_table[r_list[location].hash_entry] = -1;
                hash_table[hash_result] = location;
-               
memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+               
memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
                r_list[location].time_pos = curr_table->time_pos;
                r_list[location].addr = addr;
                r_list[location].ttl = ttl;
@@ -528,11 +529,11 @@
                if(info->check_set & IPT_RECENT_CHECK || info->check_set & 
IPT_RECENT_UPDATE) {
                        if(!info->seconds && !info->hit_count) ans = 
!info->invert; else ans = info->invert;
                        if(info->seconds && !info->hit_count) {
-                               
if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = 
!info->invert; else ans = info->invert;
+                               if(now <= 
r_list[location].last_seen+info->seconds) ans = !info->invert; else ans = 
info->invert;
                        }
                        if(info->seconds && info->hit_count) {
                                for(pkt_count = 0, hits_found = 0; pkt_count < 
ip_pkt_list_tot; pkt_count++) {
-                                       
if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) 
hits_found++;
+                                       if(now <= 
r_list[location].last_pkts[pkt_count]+info->seconds) hits_found++;
                                }
                                if(hits_found >= info->hit_count) ans = 
!info->invert; else ans = info->invert;
                        }
@@ -631,7 +632,7 @@
                        r_list[location].last_seen = 0;
                        r_list[location].addr = 0;
                        r_list[location].ttl = 0;
-                       
memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+                       
memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
                        r_list[location].oldest_pkt = 0;
                        ans = !info->invert;
                }
@@ -734,10 +735,10 @@
        memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
 #ifdef DEBUG
        if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for 
pkt_list.\n",
-                       sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+                       sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
 #endif
 
-       hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+       hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
 #ifdef DEBUG
        if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list 
allocation.\n");
 #endif
=

-------------------8<-----------------------
-- System Information:
Debian Release: 3.1
Architecture: x86_64
Kernel: Linux 2.6.8-11-amd64-k8-smp
Locale: LANG=en_US, LC_CTYPE=en_US (charmap=ANSI_X3.4-1968) (ignored: LC_ALL 
set to C)


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to