All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: justin joseph <justin.cok@gmail.com>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: bug in iptables
Date: Fri, 22 Feb 2008 15:47:41 +0100	[thread overview]
Message-ID: <47BEE08D.9070003@trash.net> (raw)
In-Reply-To: <47BED75A.9090204@trash.net>

[-- Attachment #1: Type: text/plain, Size: 698 bytes --]

Patrick McHardy wrote:
> justin joseph wrote:
>
>> root@hq.enpaq:~# uname -r
>> 2.6.15-29-386
>> root@hq.enpaq:~#
> 
> 
> Thanks, I can reproduce it on current -git. I'll look into it.


OK actually we've never had a check for this in the kernel.
Userspace contains some basic checks based on the chainname,
but this only works for the built-in chains.

This patch adds the proper checks to the kernel. I'm a bit
worried though that this might break some rulesets. So
far we've allowed to create used-defined rules with these
"invalid" matches, which might even be useful to share
chains between multiple hooks, even if some matches will
not match depending on where the jump came from.

Opinions?

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 3286 bytes --]

commit 6a90fb84a7333789aa39810ea5548342967bd27c
Author: Patrick McHardy <kaber@trash.net>
Date:   Fri Feb 22 15:45:07 2008 +0100

    [NETFILTER]: {ip,ip6}_tables: check whether interface match is used on valid hooks
    
    Input device matches are only valid in PREROUTING/INPUT/FORWARD, output
    device matches in FORWARD/OUTPUT/POSTROUTING. Iptables userspace contains
    some checks based on the chainname, catching invalid uses in the built-in
    chains, but does't catch invalid matches in user-defined chains.
    
    Add checks for valid device-match usage based on the jumps to a chain.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 600737f..0f4b16d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -155,8 +155,11 @@ ip_packet_match(const struct iphdr *ip,
 }
 
 static bool
-ip_checkentry(const struct ipt_ip *ip)
+ip_checkentry(const struct ipt_entry *e)
 {
+	const struct ipt_ip *ip = &e->ip;
+	unsigned int i;
+
 	if (ip->flags & ~IPT_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ip->flags & ~IPT_F_MASK);
@@ -167,6 +170,20 @@ ip_checkentry(const struct ipt_ip *ip)
 			 ip->invflags & ~IPT_INV_MASK);
 		return false;
 	}
+	if (e->comefrom &
+	    ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN))) {
+		for (i = 0; i < sizeof(ip->outiface); i++) {
+			if (ip->outiface_mask[i])
+				return false;
+		}
+	}
+	if (e->comefrom &
+	    ((1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_POST_ROUTING))) {
+		for (i = 0; i < sizeof(ip->iniface); i++) {
+			if (ip->iniface_mask[i])
+				return false;
+		}
+	}
 	return true;
 }
 
@@ -589,7 +606,7 @@ check_entry(struct ipt_entry *e, const char *name)
 {
 	struct ipt_entry_target *t;
 
-	if (!ip_checkentry(&e->ip)) {
+	if (!ip_checkentry(e)) {
 		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
 		return -EINVAL;
 	}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index bf9bb6e..4f0cb7c 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -184,8 +184,11 @@ ip6_packet_match(const struct sk_buff *skb,
 
 /* should be ip6 safe */
 static bool
-ip6_checkentry(const struct ip6t_ip6 *ipv6)
+ip6_checkentry(const struct ip6t_entry *e)
 {
+	const struct ip6t_ip6 *ipv6 = &e->ipv6;
+	unsigned int i;
+
 	if (ipv6->flags & ~IP6T_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ipv6->flags & ~IP6T_F_MASK);
@@ -196,6 +199,20 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6)
 			 ipv6->invflags & ~IP6T_INV_MASK);
 		return false;
 	}
+	if (e->comefrom &
+	    ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN))) {
+		for (i = 0; i < sizeof(ipv6->outiface); i++) {
+			if (ipv6->outiface_mask[i])
+				return false;
+		}
+	}
+	if (e->comefrom &
+	    ((1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_POST_ROUTING))) {
+		for (i = 0; i < sizeof(ipv6->iniface); i++) {
+			if (ipv6->iniface_mask[i])
+				return false;
+		}
+	}
 	return true;
 }
 
@@ -616,7 +633,7 @@ check_entry(struct ip6t_entry *e, const char *name)
 {
 	struct ip6t_entry_target *t;
 
-	if (!ip6_checkentry(&e->ipv6)) {
+	if (!ip6_checkentry(e)) {
 		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
 		return -EINVAL;
 	}

  reply	other threads:[~2008-02-22 14:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-14 18:38 bug in iptables justin joseph
2008-02-15  6:50 ` justin joseph
2008-02-19 12:28   ` Patrick McHardy
2008-02-22  7:26     ` justin joseph
2008-02-22 14:08       ` Patrick McHardy
2008-02-22 14:47         ` Patrick McHardy [this message]
2008-02-27 12:07           ` Patrick McHardy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47BEE08D.9070003@trash.net \
    --to=kaber@trash.net \
    --cc=justin.cok@gmail.com \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.