Root/target/linux/generic/patches-3.3/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,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@@ -561,7 +587,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@@ -570,6 +596,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@@ -931,6 +959,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@@ -961,6 +990,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;
94

Archive Download this file



interactive