Hi,

As promised, here is my fix for the string match which makes it work for
SMP boxen. The skip/shift tables are now per-CPU.

Please review.

Thanks.

-- 
// Gianni Tedesco <[EMAIL PROTECTED]>
Segmentation fault (core dumped)
--- userspace/patch-o-matic/extra/string.patch  Mon Nov 12 08:19:29 2001
+++ userspace/patch-o-matic/extra/string.patch  Thu Feb 21 20:28:37 2002
@@ -1,6 +1,6 @@
-diff -urN linux/include/linux/netfilter_ipv4/ipt_string.h 
linux.new/include/linux/netfilter_ipv4/ipt_string.h
---- linux/include/linux/netfilter_ipv4/ipt_string.h    Thu Jan  1 01:00:00 1970
-+++ linux.new/include/linux/netfilter_ipv4/ipt_string.h        Wed May  2 12:23:00 
2001
+diff -urN linux.orig/include/linux/netfilter_ipv4/ipt_string.h 
+linux/include/linux/netfilter_ipv4/ipt_string.h
+--- linux.orig/include/linux/netfilter_ipv4/ipt_string.h       Thu Jan  1 01:00:00 
+1970
++++ linux/include/linux/netfilter_ipv4/ipt_string.h    Thu Feb 21 20:26:23 2002
 @@ -0,0 +1,21 @@
 +#ifndef _IPT_STRING_H
 +#define _IPT_STRING_H
@@ -23,15 +23,18 @@
 +};
 +
 +#endif /* _IPT_STRING_H */
-diff -urN linux/net/ipv4/netfilter/ipt_string.c 
linux.new/net/ipv4/netfilter/ipt_string.c
---- linux/net/ipv4/netfilter/ipt_string.c      Thu Jan  1 01:00:00 1970
-+++ linux.new/net/ipv4/netfilter/ipt_string.c  Wed May  2 12:44:21 2001
-@@ -0,0 +1,158 @@
+diff -urN linux.orig/net/ipv4/netfilter/ipt_string.c 
+linux/net/ipv4/netfilter/ipt_string.c
+--- linux.orig/net/ipv4/netfilter/ipt_string.c Thu Jan  1 01:00:00 1970
++++ linux/net/ipv4/netfilter/ipt_string.c      Thu Feb 21 20:26:09 2002
+@@ -0,0 +1,214 @@
 +/* Kernel module to match a string into a packet.
 + *
 + * Copyright (C) 2000 Emmanuel Roger  <[EMAIL PROTECTED]>
 + * 
 + * ChangeLog
++ *    19.02.2002: Gianni Tedesco <[EMAIL PROTECTED]>
++ *            Fixed SMP re-entrancy problem using per-cpu data areas
++ *            for the skip/shift tables.
 + *    02.05.2001: Gianni Tedesco <[EMAIL PROTECTED]>
 + *            Fixed kernel panic, due to overrunning boyer moore string
 + *            tables. Also slightly tweaked heuristic for deciding what
@@ -43,6 +46,7 @@
 + *            packet basis.
 + */
 +
++#include <linux/smp.h>
 +#include <linux/module.h>
 +#include <linux/skbuff.h>
 +#include <linux/file.h>
@@ -51,18 +55,27 @@
 +#include <linux/netfilter_ipv4/ip_tables.h>
 +#include <linux/netfilter_ipv4/ipt_string.h>
 +
-+MODULE_LICENSE("GPL");
++struct string_per_cpu {
++      int *skip;
++      int *shift;
++      int *len;
++};
 +
-+int skip[BM_MAX_HLEN];
-+int shift[BM_MAX_HLEN];
++struct string_per_cpu *bm_string_data=NULL;
 +
 +/* Boyer Moore Sublinear string search - VERY FAST */
 +char *search_sublinear (char *needle, char *haystack, int needle_len, int 
 +haystack_len) 
 +{
 +      int M1, right_end, sk, sh;  
-+      int ended, j, len[BM_MAX_HLEN];
-+      int i;
++      int ended, j, i;
 +
++      int *skip, *shift, *len;
++      
++      /* use data suitable for this CPU */
++      shift=bm_string_data[smp_processor_id()].shift;
++      skip=bm_string_data[smp_processor_id()].skip;
++      len=bm_string_data[smp_processor_id()].len;
++      
 +      /* Setup skip/shift tables */
 +      M1 = right_end = needle_len-1;
 +      for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
@@ -93,7 +106,7 @@
 +              
 +              sk = skip[haystack[right_end - i]];  
 +              sh = shift[i];
-+              right_end = max(right_end - i + sk, right_end + sh);  
++              right_end = max(int, right_end - i + sk, right_end + sh);  
 +      }
 +
 +      return NULL;
@@ -170,17 +183,60 @@
 +       return 1;
 +}
 +
++void string_freeup_data(void)
++{
++      int c;
++      
++      if ( bm_string_data ) {
++              for(c=0; c<smp_num_cpus; c++) {
++                      if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
++                      if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
++                      if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
++              }
++              kfree(bm_string_data);
++      }
++}
++
 +static struct ipt_match string_match
 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
 +
 +static int __init init(void)
 +{
-+       return ipt_register_match(&string_match);
++      int c;
++      size_t tlen;
++      size_t alen;
++
++      tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
++      alen=sizeof(int)*BM_MAX_HLEN;
++      
++      /* allocate array of structures */
++      if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
++              return 0;
++      }
++      
++      memset(bm_string_data, 0, tlen);
++      
++      /* allocate our skip/shift tables */
++      for(c=0; c<smp_num_cpus; c++) {
++              if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++              if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++              if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
++                      goto alloc_fail;
++      }
++      
++      return ipt_register_match(&string_match);
++
++alloc_fail:
++      string_freeup_data();
++      return 0;
 +}
 +
 +static void __exit fini(void)
 +{
-+       ipt_unregister_match(&string_match);
++      ipt_unregister_match(&string_match);
++      string_freeup_data();
 +}
 +
 +module_init(init);

Reply via email to