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);