linux: generic: add support for 3.1-rc1
[openwrt.git] / target / linux / generic / patches-3.1 / 610-netfilter_match_bypass_default_checks.patch
1 --- a/include/linux/netfilter_ipv4/ip_tables.h
2 +++ b/include/linux/netfilter_ipv4/ip_tables.h
3 @@ -93,6 +93,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 @@ -81,6 +81,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 @@ -134,6 +137,26 @@ 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->proto)
42 +               return;
43 +
44 +       ip->flags |= IPT_F_NO_DEF_MATCH;
45 +}
46 +
47  static bool
48  ip_checkentry(const struct ipt_ip *ip)
49  {
50 @@ -561,7 +584,7 @@ static void cleanup_match(struct xt_entr
51  }
52  
53  static int
54 -check_entry(const struct ipt_entry *e, const char *name)
55 +check_entry(struct ipt_entry *e, const char *name)
56  {
57         const struct xt_entry_target *t;
58  
59 @@ -570,6 +593,8 @@ check_entry(const struct ipt_entry *e, c
60                 return -EINVAL;
61         }
62  
63 +       ip_checkdefault(&e->ip);
64 +
65         if (e->target_offset + sizeof(struct xt_entry_target) >
66             e->next_offset)
67                 return -EINVAL;
68 @@ -931,6 +956,7 @@ copy_entries_to_user(unsigned int total_
69         const struct xt_table_info *private = table->private;
70         int ret = 0;
71         const void *loc_cpu_entry;
72 +       u8 flags;
73  
74         counters = alloc_counters(table);
75         if (IS_ERR(counters))
76 @@ -961,6 +987,14 @@ copy_entries_to_user(unsigned int total_
77                         ret = -EFAULT;
78                         goto free_counters;
79                 }
80 +
81 +               flags = e->ip.flags & IPT_F_MASK;
82 +               if (copy_to_user(userptr + off
83 +                                + offsetof(struct ipt_entry, ip.flags),
84 +                                &flags, sizeof(flags)) != 0) {
85 +                       ret = -EFAULT;
86 +                       goto free_counters;
87 +               }
88  
89                 for (i = sizeof(struct ipt_entry);
90                      i < e->target_offset;