aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch')
-rw-r--r--target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch100
1 files changed, 100 insertions, 0 deletions
diff --git a/target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch
new file mode 100644
index 0000000000..480bb3ff74
--- /dev/null
+++ b/target/linux/generic/pending-4.9/610-netfilter_match_bypass_default_checks.patch
@@ -0,0 +1,100 @@
+From: Felix Fietkau <nbd@nbd.name>
+Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+ include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 +
+ net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/include/uapi/linux/netfilter_ipv4/ip_tables.h b/include/uapi/linux/netfilter_ipv4/ip_tables.h
+index d0da53d96d93..f279daa13c0f 100644
+--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
++++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
+@@ -88,6 +88,7 @@ struct ipt_ip {
+ #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
+ #define IPT_F_GOTO 0x02 /* Set if jump is a goto */
+ #define IPT_F_MASK 0x03 /* All possible flag bits mask. */
++#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
+
+ /* Values for "inv" field in struct ipt_ip. */
+ #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 7c00ce90adb8..d919350a0e8b 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -58,6 +58,9 @@ ip_packet_match(const struct iphdr *ip,
+ {
+ unsigned long ret;
+
++ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
++ return true;
++
+ if (NF_INVF(ipinfo, IPT_INV_SRCIP,
+ (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) ||
+ NF_INVF(ipinfo, IPT_INV_DSTIP,
+@@ -88,6 +91,29 @@ ip_packet_match(const struct iphdr *ip,
+ return true;
+ }
+
++static void
++ip_checkdefault(struct ipt_ip *ip)
++{
++ static const char iface_mask[IFNAMSIZ] = {};
++
++ if (ip->invflags || ip->flags & IPT_F_FRAG)
++ return;
++
++ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
++ return;
++
++ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
++ return;
++
++ if (ip->smsk.s_addr || ip->dmsk.s_addr)
++ return;
++
++ if (ip->proto)
++ return;
++
++ ip->flags |= IPT_F_NO_DEF_MATCH;
++}
++
+ static bool
+ ip_checkentry(const struct ipt_ip *ip)
+ {
+@@ -545,6 +571,8 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
+ struct xt_entry_match *ematch;
+ unsigned long pcnt;
+
++ ip_checkdefault(&e->ip);
++
+ pcnt = xt_percpu_counter_alloc();
+ if (IS_ERR_VALUE(pcnt))
+ return -ENOMEM;
+@@ -824,6 +852,7 @@ copy_entries_to_user(unsigned int total_size,
+ const struct xt_table_info *private = table->private;
+ int ret = 0;
+ const void *loc_cpu_entry;
++ u8 flags;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+@@ -851,6 +880,14 @@ copy_entries_to_user(unsigned int total_size,
+ goto free_counters;
+ }
+
++ flags = e->ip.flags & IPT_F_MASK;
++ if (copy_to_user(userptr + off
++ + offsetof(struct ipt_entry, ip.flags),
++ &flags, sizeof(flags)) != 0) {
++ ret = -EFAULT;
++ goto free_counters;
++ }
++
+ for (i = sizeof(struct ipt_entry);
+ i < e->target_offset;
+ i += m->u.match_size) {
+--
+2.11.0
+