From 9b677b44c04281cf0765063dd95d836a45cb844b Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Sun, 12 Mar 2017 14:44:03 +0100 Subject: [PATCH] kernel: update layer7 patchset Signed-off-by: Arne Fitzenreiter --- src/patches/linux/linux-4.9.13-layer7.patch | 79 +++++++++++---------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/patches/linux/linux-4.9.13-layer7.patch b/src/patches/linux/linux-4.9.13-layer7.patch index c8f5da07b..81fafb2a6 100644 --- a/src/patches/linux/linux-4.9.13-layer7.patch +++ b/src/patches/linux/linux-4.9.13-layer7.patch @@ -17,11 +17,25 @@ index 0000000..147cd64 +}; + +#endif /* _XT_LAYER7_H */ +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 32810f2..b1e6b5c 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -663,6 +663,9 @@ struct sk_buff { + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + struct nf_conntrack *nfct; + #endif ++#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) ++ char layer7_flags[1]; ++#endif + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) + struct nf_bridge_info *nf_bridge; + #endif diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h -index d9d52c0..09389b6 100644 +index d9d52c0..99b7a82 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h -@@ -120,6 +120,22 @@ struct nf_conn { +@@ -120,6 +120,23 @@ struct nf_conn { /* Extensions */ struct nf_ct_ext *ext; @@ -38,6 +52,7 @@ index d9d52c0..09389b6 100644 + */ + char *app_data; + unsigned int app_data_len; ++ unsigned int packets; + } layer7; +#endif + @@ -1483,10 +1498,10 @@ index 0000000..339631f +} diff --git a/net/netfilter/xt_layer7.c b/net/netfilter/xt_layer7.c new file mode 100644 -index 0000000..ddf7fec +index 0000000..ffdf76f --- /dev/null +++ b/net/netfilter/xt_layer7.c -@@ -0,0 +1,683 @@ +@@ -0,0 +1,671 @@ +/* + Kernel module to match application layer (OSI layer 7) data in connections. + @@ -1557,22 +1572,6 @@ index 0000000..ddf7fec + +DEFINE_SPINLOCK(l7_lock); + -+static int total_acct_packets(struct nf_conn *ct) -+{ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) -+ BUG_ON(ct == NULL); -+ return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); -+#else -+ struct nf_conn_counter *acct; -+ -+ BUG_ON(ct == NULL); -+ acct = nf_conn_acct_find(ct); -+ if (!acct) -+ return 0; -+ return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets)); -+#endif -+} -+ +#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG +/* Converts an unfriendly string into a friendly one by +replacing unprintables with periods and all whitespace with " ". */ @@ -1809,7 +1808,7 @@ index 0000000..ddf7fec + hex_print(master_conntrack->layer7.app_data); + DPRINTK("\nl7-filter gave up after %d bytes " + "(%d packets):\n%s\n", -+ strlen(f), total_acct_packets(master_conntrack), f); ++ strlen(f), master_conntrack->layer7.packets, f); + kfree(f); + DPRINTK("In hex: %s\n", g); + kfree(g); @@ -1971,19 +1970,23 @@ index 0000000..ddf7fec + while (master_ct(master_conntrack) != NULL) + master_conntrack = master_ct(master_conntrack); + ++ /* free unused conntrack data if different master conntrack exists */ ++ if (master_conntrack != conntrack) { ++ if (conntrack->layer7.app_data) { ++ DPRINTK("layer7: free unused conntrack memory.\n"); ++ kfree(conntrack->layer7.app_data); ++ conntrack->layer7.app_data = NULL; /* don't free again */ ++ } ++ } ++ + /* if we've classified it or seen too many packets */ -+ if(total_acct_packets(master_conntrack) > num_packets || ++ if( master_conntrack->layer7.packets >= num_packets || + master_conntrack->layer7.app_proto) { + + pattern_result = match_no_append(conntrack, master_conntrack, + ctinfo, master_ctinfo, info); + -+ /* skb->cb[0] == seen. Don't do things twice if there are -+ multiple l7 rules. I'm not sure that using cb for this purpose -+ is correct, even though it says "put your private variables -+ there". But it doesn't look like it is being used for anything -+ else in the skbs that make it here. */ -+ skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ ++ skb->layer7_flags[0] = 1; /* marking it seen here's probably irrelevant */ + + spin_unlock_bh(&l7_lock); + return (pattern_result ^ info->invert); @@ -2006,9 +2009,9 @@ index 0000000..ddf7fec + /* the return value gets checked later, when we're ready to use it */ + comppattern = compile_and_cache(info->pattern, info->protocol); + -+ /* On the first packet of a connection, allocate space for app data */ -+ if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] && -+ !master_conntrack->layer7.app_data){ ++ /* On fist packet of a connection, allocate space for app data */ ++ if(master_conntrack->layer7.packets==0 && !skb->layer7_flags[0] && ++ !master_conntrack->layer7.app_data){ + master_conntrack->layer7.app_data = + kmalloc(maxdatalen, GFP_ATOMIC); + if(!master_conntrack->layer7.app_data){ @@ -2022,22 +2025,22 @@ index 0000000..ddf7fec + master_conntrack->layer7.app_data[0] = '\0'; + } + -+ /* Can be here, but unallocated, if numpackets is increased near -+ the beginning of a connection */ -+ if(master_conntrack->layer7.app_data == NULL){ ++ /* this should not happen */ ++ if(master_conntrack->layer7.app_data == NULL) { + spin_unlock_bh(&l7_lock); + return info->invert; /* unmatched */ + } + -+ if(!skb->cb[0]){ ++ if(!skb->layer7_flags[0]){ + int newbytes; + newbytes = add_data(master_conntrack, app_data, appdatalen); + if(newbytes == 0) { /* didn't add any data */ -+ skb->cb[0] = 1; ++ skb->layer7_flags[0] = 1; + /* Didn't match before, not going to match now */ + spin_unlock_bh(&l7_lock); + return info->invert; + } ++ master_conntrack->layer7.packets++; + } + + /* If looking for "unknown", then never match. "Unknown" means that @@ -2050,7 +2053,7 @@ index 0000000..ddf7fec + pattern_result = 2; + DPRINTK("layer7: matched unset: not yet classified " + "(%d/%d packets)\n", -+ total_acct_packets(master_conntrack), num_packets); ++ master_conntrack->layer7.packets, num_packets); + /* If the regexp failed to compile, don't bother running it */ + } else if(comppattern && + regexec(comppattern, master_conntrack->layer7.app_data)){ @@ -2065,7 +2068,7 @@ index 0000000..ddf7fec + } + + /* mark the packet seen */ -+ skb->cb[0] = 1; ++ skb->layer7_flags[0] = 1; + + spin_unlock_bh(&l7_lock); + return (pattern_result ^ info->invert);