Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: fix string extension for case insensitive pattern matching

The flag XT_STRING_FLAG_IGNORECASE indicates case insensitive string
matching. netfilter can find cmd.exe, Cmd.exe, cMd.exe and etc easily.

A new revision 1 was added, in the meantime invert of xt_string_info
was moved into flags as a flag. If revision is 1, The flag
XT_STRING_FLAG_INVERT indicates invert matching.

Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Joonwoo Park and committed by
David S. Miller
4ad3f261 dde77e60

+50 -3
+14 -1
include/linux/netfilter/xt_string.h
··· 4 4 #define XT_STRING_MAX_PATTERN_SIZE 128 5 5 #define XT_STRING_MAX_ALGO_NAME_SIZE 16 6 6 7 + enum { 8 + XT_STRING_FLAG_INVERT = 0x01, 9 + XT_STRING_FLAG_IGNORECASE = 0x02 10 + }; 11 + 7 12 struct xt_string_info 8 13 { 9 14 u_int16_t from_offset; ··· 16 11 char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; 17 12 char pattern[XT_STRING_MAX_PATTERN_SIZE]; 18 13 u_int8_t patlen; 19 - u_int8_t invert; 14 + union { 15 + struct { 16 + u_int8_t invert; 17 + } v0; 18 + 19 + struct { 20 + u_int8_t flags; 21 + } v1; 22 + } u; 20 23 21 24 /* Used internally by the kernel */ 22 25 struct ts_config __attribute__((aligned(8))) *config;
+36 -2
net/netfilter/xt_string.c
··· 29 29 { 30 30 const struct xt_string_info *conf = matchinfo; 31 31 struct ts_state state; 32 + int invert; 32 33 33 34 memset(&state, 0, sizeof(struct ts_state)); 34 35 36 + invert = (match->revision == 0 ? conf->u.v0.invert : 37 + conf->u.v1.flags & XT_STRING_FLAG_INVERT); 38 + 35 39 return (skb_find_text((struct sk_buff *)skb, conf->from_offset, 36 40 conf->to_offset, conf->config, &state) 37 - != UINT_MAX) ^ conf->invert; 41 + != UINT_MAX) ^ invert; 38 42 } 39 43 40 44 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m)) ··· 50 46 { 51 47 struct xt_string_info *conf = matchinfo; 52 48 struct ts_config *ts_conf; 49 + int flags = TS_AUTOLOAD; 53 50 54 51 /* Damn, can't handle this case properly with iptables... */ 55 52 if (conf->from_offset > conf->to_offset) ··· 59 54 return false; 60 55 if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) 61 56 return false; 57 + if (match->revision == 1) { 58 + if (conf->u.v1.flags & 59 + ~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT)) 60 + return false; 61 + if (conf->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 62 + flags |= TS_IGNORECASE; 63 + } 62 64 ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, 63 - GFP_KERNEL, TS_AUTOLOAD); 65 + GFP_KERNEL, flags); 64 66 if (IS_ERR(ts_conf)) 65 67 return false; 66 68 ··· 84 72 static struct xt_match string_mt_reg[] __read_mostly = { 85 73 { 86 74 .name = "string", 75 + .revision = 0, 87 76 .family = AF_INET, 88 77 .checkentry = string_mt_check, 89 78 .match = string_mt, ··· 94 81 }, 95 82 { 96 83 .name = "string", 84 + .revision = 1, 85 + .family = AF_INET, 86 + .checkentry = string_mt_check, 87 + .match = string_mt, 88 + .destroy = string_mt_destroy, 89 + .matchsize = sizeof(struct xt_string_info), 90 + .me = THIS_MODULE 91 + }, 92 + { 93 + .name = "string", 94 + .revision = 0, 95 + .family = AF_INET6, 96 + .checkentry = string_mt_check, 97 + .match = string_mt, 98 + .destroy = string_mt_destroy, 99 + .matchsize = sizeof(struct xt_string_info), 100 + .me = THIS_MODULE 101 + }, 102 + { 103 + .name = "string", 104 + .revision = 1, 97 105 .family = AF_INET6, 98 106 .checkentry = string_mt_check, 99 107 .match = string_mt,