kernel: split patches folder up into backport, pending and hack folders
[openwrt/openwrt.git] / target / linux / generic / pending-4.9 / 610-netfilter_match_bypass_default_checks.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0
3
4 Signed-off-by: Felix Fietkau <nbd@nbd.name>
5 ---
6 include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 +
7 net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++
8 2 files changed, 38 insertions(+)
9
10 diff --git a/include/uapi/linux/netfilter_ipv4/ip_tables.h b/include/uapi/linux/netfilter_ipv4/ip_tables.h
11 index d0da53d96d93..f279daa13c0f 100644
12 --- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
13 +++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
14 @@ -88,6 +88,7 @@ struct ipt_ip {
15 #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
16 #define IPT_F_GOTO 0x02 /* Set if jump is a goto */
17 #define IPT_F_MASK 0x03 /* All possible flag bits mask. */
18 +#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
19
20 /* Values for "inv" field in struct ipt_ip. */
21 #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
22 diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
23 index 7c00ce90adb8..d919350a0e8b 100644
24 --- a/net/ipv4/netfilter/ip_tables.c
25 +++ b/net/ipv4/netfilter/ip_tables.c
26 @@ -58,6 +58,9 @@ ip_packet_match(const struct iphdr *ip,
27 {
28 unsigned long ret;
29
30 + if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
31 + return true;
32 +
33 if (NF_INVF(ipinfo, IPT_INV_SRCIP,
34 (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) ||
35 NF_INVF(ipinfo, IPT_INV_DSTIP,
36 @@ -88,6 +91,29 @@ ip_packet_match(const struct iphdr *ip,
37 return true;
38 }
39
40 +static void
41 +ip_checkdefault(struct ipt_ip *ip)
42 +{
43 + static const char iface_mask[IFNAMSIZ] = {};
44 +
45 + if (ip->invflags || ip->flags & IPT_F_FRAG)
46 + return;
47 +
48 + if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
49 + return;
50 +
51 + if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
52 + return;
53 +
54 + if (ip->smsk.s_addr || ip->dmsk.s_addr)
55 + return;
56 +
57 + if (ip->proto)
58 + return;
59 +
60 + ip->flags |= IPT_F_NO_DEF_MATCH;
61 +}
62 +
63 static bool
64 ip_checkentry(const struct ipt_ip *ip)
65 {
66 @@ -545,6 +571,8 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
67 struct xt_entry_match *ematch;
68 unsigned long pcnt;
69
70 + ip_checkdefault(&e->ip);
71 +
72 pcnt = xt_percpu_counter_alloc();
73 if (IS_ERR_VALUE(pcnt))
74 return -ENOMEM;
75 @@ -824,6 +852,7 @@ copy_entries_to_user(unsigned int total_size,
76 const struct xt_table_info *private = table->private;
77 int ret = 0;
78 const void *loc_cpu_entry;
79 + u8 flags;
80
81 counters = alloc_counters(table);
82 if (IS_ERR(counters))
83 @@ -851,6 +880,14 @@ copy_entries_to_user(unsigned int total_size,
84 goto free_counters;
85 }
86
87 + flags = e->ip.flags & IPT_F_MASK;
88 + if (copy_to_user(userptr + off
89 + + offsetof(struct ipt_entry, ip.flags),
90 + &flags, sizeof(flags)) != 0) {
91 + ret = -EFAULT;
92 + goto free_counters;
93 + }
94 +
95 for (i = sizeof(struct ipt_entry);
96 i < e->target_offset;
97 i += m->u.match_size) {
98 --
99 2.11.0
100