pending-3.18: 610-netfilter_match_bypass_default_check: fix 32bit compat layer
[openwrt/openwrt.git] / target / linux / generic / pending-3.18 / 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 @@ -650,6 +676,8 @@ find_check_entry(struct ipt_entry *e, st
54 struct xt_mtchk_param mtpar;
55 struct xt_entry_match *ematch;
56
57 + ip_checkdefault(&e->ip);
58 +
59 j = 0;
60 mtpar.net = net;
61 mtpar.table = name;
62 @@ -942,6 +970,7 @@ copy_entries_to_user(unsigned int total_
63 const struct xt_table_info *private = table->private;
64 int ret = 0;
65 const void *loc_cpu_entry;
66 + u8 flags;
67
68 counters = alloc_counters(table);
69 if (IS_ERR(counters))
70 @@ -973,6 +1002,14 @@ copy_entries_to_user(unsigned int total_
71 goto free_counters;
72 }
73
74 + flags = e->ip.flags & IPT_F_MASK;
75 + if (copy_to_user(userptr + off
76 + + offsetof(struct ipt_entry, ip.flags),
77 + &flags, sizeof(flags)) != 0) {
78 + ret = -EFAULT;
79 + goto free_counters;
80 + }
81 +
82 for (i = sizeof(struct ipt_entry);
83 i < e->target_offset;
84 i += m->u.match_size) {
85 @@ -1379,12 +1416,15 @@ compat_copy_entry_to_user(struct ipt_ent
86 compat_uint_t origsize;
87 const struct xt_entry_match *ematch;
88 int ret = 0;
89 + u8 flags = e->ip.flags & IPT_F_MASK;
90
91 origsize = *size;
92 ce = (struct compat_ipt_entry __user *)*dstptr;
93 if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
94 copy_to_user(&ce->counters, &counters[i],
95 - sizeof(counters[i])) != 0)
96 + sizeof(counters[i])) != 0 ||
97 + copy_to_user(&ce->ip.flags, &flags,
98 + sizeof(flags)) != 0)
99 return -EFAULT;
100
101 *dstptr += sizeof(struct compat_ipt_entry);