kernel: add missing checks in the netfilter optimization patch which broke some rules containing only source/destination address checks

SVN-Revision: 27923
owl
Felix Fietkau 2011-08-06 12:39:31 +00:00
parent a1d5ad7655
commit ac96ae6731
4 changed files with 25 additions and 19 deletions

View File

@ -20,7 +20,7 @@
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) || IPT_INV_SRCIP) ||
FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
@@ -143,6 +146,26 @@ ip_packet_match(const struct iphdr *ip, @@ -143,6 +146,29 @@ ip_packet_match(const struct iphdr *ip,
return true; return true;
} }
@ -38,6 +38,9 @@
+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) + if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+ return; + return;
+ +
+ if (ip->smsk.s_addr || ip->dmsk.s_addr)
+ return;
+
+ if (ip->proto) + if (ip->proto)
+ return; + return;
+ +
@ -47,7 +50,7 @@
static bool static bool
ip_checkentry(const struct ipt_ip *ip) ip_checkentry(const struct ipt_ip *ip)
{ {
@@ -566,7 +589,7 @@ static void cleanup_match(struct xt_entr @@ -566,7 +592,7 @@ static void cleanup_match(struct xt_entr
} }
static int static int
@ -56,7 +59,7 @@
{ {
const struct xt_entry_target *t; const struct xt_entry_target *t;
@@ -575,6 +598,8 @@ check_entry(const struct ipt_entry *e, c @@ -575,6 +601,8 @@ check_entry(const struct ipt_entry *e, c
return -EINVAL; return -EINVAL;
} }
@ -65,7 +68,7 @@
if (e->target_offset + sizeof(struct xt_entry_target) > if (e->target_offset + sizeof(struct xt_entry_target) >
e->next_offset) e->next_offset)
return -EINVAL; return -EINVAL;
@@ -936,6 +961,7 @@ copy_entries_to_user(unsigned int total_ @@ -936,6 +964,7 @@ copy_entries_to_user(unsigned int total_
const struct xt_table_info *private = table->private; const struct xt_table_info *private = table->private;
int ret = 0; int ret = 0;
const void *loc_cpu_entry; const void *loc_cpu_entry;
@ -73,7 +76,7 @@
counters = alloc_counters(table); counters = alloc_counters(table);
if (IS_ERR(counters)) if (IS_ERR(counters))
@@ -967,6 +993,14 @@ copy_entries_to_user(unsigned int total_ @@ -967,6 +996,14 @@ copy_entries_to_user(unsigned int total_
goto free_counters; goto free_counters;
} }

View File

@ -1,6 +1,6 @@
--- a/net/ipv4/netfilter/ip_tables.c --- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c
@@ -316,6 +316,33 @@ struct ipt_entry *ipt_next_entry(const s @@ -319,6 +319,33 @@ struct ipt_entry *ipt_next_entry(const s
return (void *)entry + entry->next_offset; return (void *)entry + entry->next_offset;
} }
@ -34,7 +34,7 @@
/* Returns one of the generic firewall policies, like NF_ACCEPT. */ /* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int unsigned int
ipt_do_table(struct sk_buff *skb, ipt_do_table(struct sk_buff *skb,
@@ -339,6 +366,23 @@ ipt_do_table(struct sk_buff *skb, @@ -342,6 +369,23 @@ ipt_do_table(struct sk_buff *skb,
ip = ip_hdr(skb); ip = ip_hdr(skb);
indev = in ? in->name : nulldevname; indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname; outdev = out ? out->name : nulldevname;
@ -58,7 +58,7 @@
/* We handle fragments by dealing with the first fragment as /* We handle fragments by dealing with the first fragment as
* if it was a normal packet. All other fragments are treated * if it was a normal packet. All other fragments are treated
* normally, except that they will NEVER match rules that ask * normally, except that they will NEVER match rules that ask
@@ -353,17 +397,6 @@ ipt_do_table(struct sk_buff *skb, @@ -356,17 +400,6 @@ ipt_do_table(struct sk_buff *skb,
acpar.family = NFPROTO_IPV4; acpar.family = NFPROTO_IPV4;
acpar.hooknum = hook; acpar.hooknum = hook;

View File

@ -20,7 +20,7 @@
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) || IPT_INV_SRCIP) ||
FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
@@ -134,6 +137,26 @@ ip_packet_match(const struct iphdr *ip, @@ -134,6 +137,29 @@ ip_packet_match(const struct iphdr *ip,
return true; return true;
} }
@ -38,6 +38,9 @@
+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) + if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+ return; + return;
+ +
+ if (ip->smsk.s_addr || ip->dmsk.s_addr)
+ return;
+
+ if (ip->proto) + if (ip->proto)
+ return; + return;
+ +
@ -47,7 +50,7 @@
static bool static bool
ip_checkentry(const struct ipt_ip *ip) ip_checkentry(const struct ipt_ip *ip)
{ {
@@ -561,7 +584,7 @@ static void cleanup_match(struct xt_entr @@ -561,7 +587,7 @@ static void cleanup_match(struct xt_entr
} }
static int static int
@ -56,7 +59,7 @@
{ {
const struct xt_entry_target *t; const struct xt_entry_target *t;
@@ -570,6 +593,8 @@ check_entry(const struct ipt_entry *e, c @@ -570,6 +596,8 @@ check_entry(const struct ipt_entry *e, c
return -EINVAL; return -EINVAL;
} }
@ -65,7 +68,7 @@
if (e->target_offset + sizeof(struct xt_entry_target) > if (e->target_offset + sizeof(struct xt_entry_target) >
e->next_offset) e->next_offset)
return -EINVAL; return -EINVAL;
@@ -931,6 +956,7 @@ copy_entries_to_user(unsigned int total_ @@ -931,6 +959,7 @@ copy_entries_to_user(unsigned int total_
const struct xt_table_info *private = table->private; const struct xt_table_info *private = table->private;
int ret = 0; int ret = 0;
const void *loc_cpu_entry; const void *loc_cpu_entry;
@ -73,11 +76,10 @@
counters = alloc_counters(table); counters = alloc_counters(table);
if (IS_ERR(counters)) if (IS_ERR(counters))
@@ -961,6 +987,14 @@ copy_entries_to_user(unsigned int total_ @@ -962,6 +991,14 @@ copy_entries_to_user(unsigned int total_
ret = -EFAULT;
goto free_counters; goto free_counters;
} }
+
+ flags = e->ip.flags & IPT_F_MASK; + flags = e->ip.flags & IPT_F_MASK;
+ if (copy_to_user(userptr + off + if (copy_to_user(userptr + off
+ + offsetof(struct ipt_entry, ip.flags), + + offsetof(struct ipt_entry, ip.flags),
@ -85,6 +87,7 @@
+ ret = -EFAULT; + ret = -EFAULT;
+ goto free_counters; + goto free_counters;
+ } + }
+
for (i = sizeof(struct ipt_entry); for (i = sizeof(struct ipt_entry);
i < e->target_offset; i < e->target_offset;
i += m->u.match_size) {

View File

@ -1,6 +1,6 @@
--- a/net/ipv4/netfilter/ip_tables.c --- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c
@@ -307,6 +307,33 @@ struct ipt_entry *ipt_next_entry(const s @@ -310,6 +310,33 @@ struct ipt_entry *ipt_next_entry(const s
return (void *)entry + entry->next_offset; return (void *)entry + entry->next_offset;
} }
@ -34,7 +34,7 @@
/* Returns one of the generic firewall policies, like NF_ACCEPT. */ /* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int unsigned int
ipt_do_table(struct sk_buff *skb, ipt_do_table(struct sk_buff *skb,
@@ -331,6 +358,25 @@ ipt_do_table(struct sk_buff *skb, @@ -334,6 +361,25 @@ ipt_do_table(struct sk_buff *skb,
ip = ip_hdr(skb); ip = ip_hdr(skb);
indev = in ? in->name : nulldevname; indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname; outdev = out ? out->name : nulldevname;
@ -60,7 +60,7 @@
/* We handle fragments by dealing with the first fragment as /* We handle fragments by dealing with the first fragment as
* if it was a normal packet. All other fragments are treated * if it was a normal packet. All other fragments are treated
* normally, except that they will NEVER match rules that ask * normally, except that they will NEVER match rules that ask
@@ -345,18 +391,6 @@ ipt_do_table(struct sk_buff *skb, @@ -348,18 +394,6 @@ ipt_do_table(struct sk_buff *skb,
acpar.family = NFPROTO_IPV4; acpar.family = NFPROTO_IPV4;
acpar.hooknum = hook; acpar.hooknum = hook;