kernel: split patches folder up into backport, pending and hack folders
[lede-git/.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