brcm47xx: drop 3.14
[openwrt.git] / target / linux / generic / patches-3.14 / 610-netfilter_match_bypass_default_checks.patch
1 --- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
2 +++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
3 @@ -87,6 +87,7 @@ struct ipt_ip {
4  #define IPT_F_FRAG             0x01    /* Set if rule is a fragment rule */
5  #define IPT_F_GOTO             0x02    /* Set if jump is a goto */
6  #define IPT_F_MASK             0x03    /* All possible flag bits mask. */
7 +#define IPT_F_NO_DEF_MATCH     0x80    /* Internal: no default match rules present */
8  
9  /* Values for "inv" field in struct ipt_ip. */
10  #define IPT_INV_VIA_IN         0x01    /* Invert the sense of IN IFACE. */
11 --- a/net/ipv4/netfilter/ip_tables.c
12 +++ b/net/ipv4/netfilter/ip_tables.c
13 @@ -82,6 +82,9 @@ ip_packet_match(const struct iphdr *ip,
14  
15  #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
16  
17 +       if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
18 +               return true;
19 +
20         if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
21                   IPT_INV_SRCIP) ||
22             FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
23 @@ -135,6 +138,29 @@ ip_packet_match(const struct iphdr *ip,
24         return true;
25  }
26  
27 +static void
28 +ip_checkdefault(struct ipt_ip *ip)
29 +{
30 +       static const char iface_mask[IFNAMSIZ] = {};
31 +
32 +       if (ip->invflags || ip->flags & IPT_F_FRAG)
33 +               return;
34 +
35 +       if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
36 +               return;
37 +
38 +       if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
39 +               return;
40 +
41 +       if (ip->smsk.s_addr || ip->dmsk.s_addr)
42 +               return;
43 +
44 +       if (ip->proto)
45 +               return;
46 +
47 +       ip->flags |= IPT_F_NO_DEF_MATCH;
48 +}
49 +
50  static bool
51  ip_checkentry(const struct ipt_ip *ip)
52  {
53 @@ -565,7 +591,7 @@ static void cleanup_match(struct xt_entr
54  }
55  
56  static int
57 -check_entry(const struct ipt_entry *e, const char *name)
58 +check_entry(struct ipt_entry *e, const char *name)
59  {
60         const struct xt_entry_target *t;
61  
62 @@ -574,6 +600,8 @@ check_entry(const struct ipt_entry *e, c
63                 return -EINVAL;
64         }
65  
66 +       ip_checkdefault(&e->ip);
67 +
68         if (e->target_offset + sizeof(struct xt_entry_target) >
69             e->next_offset)
70                 return -EINVAL;
71 @@ -935,6 +963,7 @@ copy_entries_to_user(unsigned int total_
72         const struct xt_table_info *private = table->private;
73         int ret = 0;
74         const void *loc_cpu_entry;
75 +       u8 flags;
76  
77         counters = alloc_counters(table);
78         if (IS_ERR(counters))
79 @@ -965,6 +994,14 @@ copy_entries_to_user(unsigned int total_
80                         ret = -EFAULT;
81                         goto free_counters;
82                 }
83 +
84 +               flags = e->ip.flags & IPT_F_MASK;
85 +               if (copy_to_user(userptr + off
86 +                                + offsetof(struct ipt_entry, ip.flags),
87 +                                &flags, sizeof(flags)) != 0) {
88 +                       ret = -EFAULT;
89 +                       goto free_counters;
90 +               }
91  
92                 for (i = sizeof(struct ipt_entry);
93                      i < e->target_offset;