This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 2.x development tree".
The branch, master has been updated via c3a86f4d20c066b3843a57542e3782ccef18e757 (commit) from 8d2fe8cedd68bfdf648df1baf8b654a846f8c022 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit c3a86f4d20c066b3843a57542e3782ccef18e757 Author: Michael Tremer michael.tremer@ipfire.org Date: Fri Apr 18 23:11:39 2014 +0200
Update layer7 patch.
This should fix some issues with concurrent access to skbuf.
-----------------------------------------------------------------------
Summary of changes: src/patches/linux-3.10-layer7-filter.patch | 148 ++++++++++++++++++----------- 1 file changed, 94 insertions(+), 54 deletions(-)
Difference in files: diff --git a/src/patches/linux-3.10-layer7-filter.patch b/src/patches/linux-3.10-layer7-filter.patch index 4cf2a1c..ec5fc5d 100644 --- a/src/patches/linux-3.10-layer7-filter.patch +++ b/src/patches/linux-3.10-layer7-filter.patch @@ -1514,10 +1514,10 @@ index 0000000..339631f +} diff --git a/net/netfilter/xt_layer7.c b/net/netfilter/xt_layer7.c new file mode 100644 -index 0000000..51bb747 +index 0000000..1573e9d --- /dev/null +++ b/net/netfilter/xt_layer7.c -@@ -0,0 +1,625 @@ +@@ -0,0 +1,665 @@ +/* + Kernel module to match application layer (OSI layer 7) data in connections. + @@ -1726,40 +1726,67 @@ index 0000000..51bb747 + +static int can_handle(const struct sk_buff *skb) +{ -+ if(!ip_hdr(skb)) /* not IP */ ++ struct iphdr iphdr_tmp; ++ struct iphdr *iphdr; ++ int offset; ++ ++ if (!ip_hdr(skb)) + return 0; -+ if(ip_hdr(skb)->protocol != IPPROTO_TCP && -+ ip_hdr(skb)->protocol != IPPROTO_UDP && -+ ip_hdr(skb)->protocol != IPPROTO_ICMP) ++ ++ offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data); ++ ++ iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp); ++ if (!iphdr) + return 0; -+ return 1; ++ ++ if (iphdr->protocol == IPPROTO_TCP || ++ iphdr->protocol == IPPROTO_UDP || ++ iphdr->protocol == IPPROTO_ICMP) ++ return 1; ++ ++ return 0; +} + -+/* Returns offset the into the skb->data that the application data starts */ +static int app_data_offset(const struct sk_buff *skb) +{ -+ /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) -+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ -+ int ip_hl = 4*ip_hdr(skb)->ihl; -+ -+ if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { -+ /* 12 == offset into TCP header for the header length field. -+ Can't get this with skb->h.th->doff because the tcphdr -+ struct doesn't get set when routing (this is confirmed to be -+ true in Netfilter as well as QoS.) */ -+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); -+ -+ return ip_hl + tcp_hl; -+ } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) { -+ return ip_hl + 8; /* UDP header is always 8 bytes */ -+ } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { -+ return ip_hl + 8; /* ICMP header is 8 bytes */ -+ } else { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: tried to handle unknown " -+ "protocol!\n"); -+ return ip_hl + 8; /* something reasonable */ ++ int offset; ++ struct iphdr iphdr_tmp; ++ struct iphdr *iphdr; ++ struct tcphdr tcphdr_tmp; ++ struct tcphdr *tcphdr; ++ ++ if (!ip_hdr(skb)) ++ return -1; ++ ++ offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data); ++ ++ iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp); ++ if (!iphdr) ++ return -1; ++ ++ offset += iphdr->ihl * 4; ++ ++ if (iphdr->protocol == IPPROTO_TCP) { ++ tcphdr = skb_header_pointer(skb, offset, sizeof(*tcphdr), ++ &tcphdr_tmp); ++ if (!tcphdr) ++ return -1; ++ ++ offset += tcphdr->doff * 4; ++ ++ return offset; + } ++ ++ if (iphdr->protocol == IPPROTO_UDP) ++ return offset + 8; ++ ++ if (iphdr->protocol == IPPROTO_ICMP) ++ return offset + 8; ++ ++ if (net_ratelimit()) ++ pr_err(KERN_ERR "layer7: tried to handle unknown protocol!\n"); ++ ++ return offset + 8; /* something reasonable */ +} + +/* handles whether there's a match when we aren't appending data anymore */ @@ -1849,13 +1876,39 @@ index 0000000..51bb747 + return length; +} + ++/* add the new app data to the buffer. Return number of bytes added. */ ++static int add_data(char *target, int offset, const struct sk_buff *skb) ++{ ++ int length, length_sum = 0; ++ int data_start = app_data_offset(skb); ++ int remaining = skb->len - data_start; ++ int to_copy; ++ uint8_t buf[512]; ++ uint8_t *data; ++ ++ while ((offset < maxdatalen - 1) && (remaining > 0)) { ++ to_copy = min_t(int, remaining, sizeof(buf)); ++ ++ data = skb_header_pointer(skb, data_start, to_copy, buf); ++ length = add_datastr(target, offset, data, to_copy); ++ ++ remaining -= to_copy; ++ data_start += to_copy; ++ offset += length; ++ length_sum += length; ++ } ++ ++ return length_sum; ++} ++ +/* add the new app data to the conntrack. Return number of bytes added. */ -+static int add_data(struct nf_conn * master_conntrack, -+ char * app_data, int appdatalen) ++static int add_data_conntrack(struct nf_conn *master_conntrack, ++ const struct sk_buff *skb) +{ + int length; + -+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen); ++ length = add_data(master_conntrack->layer7.app_data, ++ master_conntrack->layer7.app_data_len, skb); + master_conntrack->layer7.app_data_len += length; + + return length; @@ -1911,20 +1964,20 @@ index 0000000..51bb747 +static bool match(const struct sk_buff *skbin, struct xt_action_param *par) +{ + /* sidestep const without getting a compiler warning... */ -+ struct sk_buff * skb = (struct sk_buff *)skbin; ++ struct sk_buff *skb = (struct sk_buff *)skbin; + + const struct xt_layer7_info * info = par->matchinfo; + + enum ip_conntrack_info master_ctinfo, ctinfo; + struct nf_conn *master_conntrack, *conntrack; -+ unsigned char *app_data, *tmp_data; -+ unsigned int pattern_result, appdatalen; ++ unsigned char *tmp_data; ++ unsigned int pattern_result; + regexp * comppattern; + + /* Be paranoid/incompetent - lock the entire match function. */ + spin_lock_bh(&l7_lock); + -+ if(!can_handle(skb)){ ++ if (!can_handle(skbin)) { + DPRINTK("layer7: This is some protocol I can't handle.\n"); + spin_unlock_bh(&l7_lock); + return info->invert; @@ -1933,8 +1986,9 @@ index 0000000..51bb747 + /* Treat parent & all its children together as one connection, except + for the purpose of setting conntrack->layer7.app_proto in the actual + connection. This makes /proc/net/ip_conntrack more satisfying. */ -+ if(!(conntrack = nf_ct_get(skb, &ctinfo)) || -+ !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ ++ conntrack = nf_ct_get(skbin, &ctinfo); ++ master_conntrack = nf_ct_get(skbin, &master_ctinfo); ++ if (!conntrack || !master_conntrack) { + DPRINTK("layer7: couldn't get conntrack.\n"); + spin_unlock_bh(&l7_lock); + return info->invert; @@ -1962,20 +2016,6 @@ index 0000000..51bb747 + return (pattern_result ^ info->invert); + } + -+ if(skb_is_nonlinear(skb)){ -+ if(skb_linearize(skb) != 0){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: failed to linearize " -+ "packet, bailing.\n"); -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ } -+ -+ /* now that the skb is linearized, it's safe to set these. */ -+ app_data = skb->data + app_data_offset(skb); -+ appdatalen = skb_tail_pointer(skb) - app_data; -+ + /* the return value gets checked later, when we're ready to use it */ + comppattern = compile_and_cache(info->pattern, info->protocol); + @@ -1988,7 +2028,7 @@ index 0000000..51bb747 + } + + tmp_data[0] = '\0'; -+ add_datastr(tmp_data, 0, app_data, appdatalen); ++ add_data(tmp_data, 0, skbin); + pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0); + + kfree(tmp_data); @@ -2023,7 +2063,7 @@ index 0000000..51bb747 + + if(!skb->cb[0]){ + int newbytes; -+ newbytes = add_data(master_conntrack, app_data, appdatalen); ++ newbytes = add_data_conntrack(master_conntrack, skb); + + if(newbytes == 0) { /* didn't add any data */ + skb->cb[0] = 1;
hooks/post-receive -- IPFire 2.x development tree