From: Patrick McHardy <kaber@trash.net>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, Patrick McHardy <kaber@trash.net>,
netfilter-devel@vger.kernel.org
Subject: netfilter 07/08: xtables: fix conntrack match v1 ipt-save output
Date: Thu, 3 Dec 2009 21:19:41 +0100 (MET) [thread overview]
Message-ID: <20091203201940.8831.2282.sendpatchset@x2.localnet> (raw)
In-Reply-To: <20091203201931.8831.92922.sendpatchset@x2.localnet>
commit 3a0429292daa0e1ec848bd26479f5e48b0d54a42
Author: Florian Westphal <fw@strlen.de>
Date: Mon Nov 23 10:43:57 2009 +0100
netfilter: xtables: fix conntrack match v1 ipt-save output
commit d6d3f08b0fd998b647a05540cedd11a067b72867
(netfilter: xtables: conntrack match revision 2) does break the
v1 conntrack match iptables-save output in a subtle way.
Problem is as follows:
up = kmalloc(sizeof(*up), GFP_KERNEL);
[..]
/*
* The strategy here is to minimize the overhead of v1 matching,
* by prebuilding a v2 struct and putting the pointer into the
* v1 dataspace.
*/
memcpy(up, info, offsetof(typeof(*info), state_mask));
[..]
*(void **)info = up;
As the v2 struct pointer is saved in the match data space,
it clobbers the first structure member (->origsrc_addr).
Because the _v1 match function grabs this pointer and does not actually
look at the v1 origsrc, run time functionality does not break.
But iptables -nvL (or iptables-save) cannot know that v1 origsrc_addr
has been overloaded in this way:
$ iptables -p tcp -A OUTPUT -m conntrack --ctorigsrc 10.0.0.1 -j ACCEPT
$ iptables-save
-A OUTPUT -p tcp -m conntrack --ctorigsrc 128.173.134.206 -j ACCEPT
(128.173... is the address to the v2 match structure).
To fix this, we take advantage of the fact that the v1 and v2 structures
are identical with exception of the last two structure members (u8 in v1,
u16 in v2).
We extract them as early as possible and prevent the v2 matching function
from looking at those two members directly.
Previously reported by Michel Messerschmidt via Ben Hutchings, also
see Debian Bug tracker #556587.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 6dc4652..ae66305 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -113,7 +113,8 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info,
}
static bool
-conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par,
+ u16 state_mask, u16 status_mask)
{
const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
enum ip_conntrack_info ctinfo;
@@ -136,7 +137,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
if (test_bit(IPS_DST_NAT_BIT, &ct->status))
statebit |= XT_CONNTRACK_STATE_DNAT;
}
- if (!!(info->state_mask & statebit) ^
+ if (!!(state_mask & statebit) ^
!(info->invert_flags & XT_CONNTRACK_STATE))
return false;
}
@@ -172,7 +173,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
return false;
if ((info->match_flags & XT_CONNTRACK_STATUS) &&
- (!!(info->status_mask & ct->status) ^
+ (!!(status_mask & ct->status) ^
!(info->invert_flags & XT_CONNTRACK_STATUS)))
return false;
@@ -192,11 +193,17 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
static bool
conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo;
- struct xt_match_param newpar = *par;
+ const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
- newpar.matchinfo = *info;
- return conntrack_mt(skb, &newpar);
+ return conntrack_mt(skb, par, info->state_mask, info->status_mask);
+}
+
+static bool
+conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+ const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
+
+ return conntrack_mt(skb, par, info->state_mask, info->status_mask);
}
static bool conntrack_mt_check(const struct xt_mtchk_param *par)
@@ -209,45 +216,11 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par)
return true;
}
-static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par)
-{
- struct xt_conntrack_mtinfo1 *info = par->matchinfo;
- struct xt_conntrack_mtinfo2 *up;
- int ret = conntrack_mt_check(par);
-
- if (ret < 0)
- return ret;
-
- up = kmalloc(sizeof(*up), GFP_KERNEL);
- if (up == NULL) {
- nf_ct_l3proto_module_put(par->family);
- return -ENOMEM;
- }
-
- /*
- * The strategy here is to minimize the overhead of v1 matching,
- * by prebuilding a v2 struct and putting the pointer into the
- * v1 dataspace.
- */
- memcpy(up, info, offsetof(typeof(*info), state_mask));
- up->state_mask = info->state_mask;
- up->status_mask = info->status_mask;
- *(void **)info = up;
- return true;
-}
-
static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
{
nf_ct_l3proto_module_put(par->family);
}
-static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par)
-{
- struct xt_conntrack_mtinfo2 **info = par->matchinfo;
- kfree(*info);
- conntrack_mt_destroy(par);
-}
-
static struct xt_match conntrack_mt_reg[] __read_mostly = {
{
.name = "conntrack",
@@ -255,8 +228,8 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
.family = NFPROTO_UNSPEC,
.matchsize = sizeof(struct xt_conntrack_mtinfo1),
.match = conntrack_mt_v1,
- .checkentry = conntrack_mt_check_v1,
- .destroy = conntrack_mt_destroy_v1,
+ .checkentry = conntrack_mt_check,
+ .destroy = conntrack_mt_destroy,
.me = THIS_MODULE,
},
{
@@ -264,7 +237,7 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
.revision = 2,
.family = NFPROTO_UNSPEC,
.matchsize = sizeof(struct xt_conntrack_mtinfo2),
- .match = conntrack_mt,
+ .match = conntrack_mt_v2,
.checkentry = conntrack_mt_check,
.destroy = conntrack_mt_destroy,
.me = THIS_MODULE,
next prev parent reply other threads:[~2009-12-03 20:19 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-03 20:19 netfilter 00/08: Netfilter Update Patrick McHardy
2009-12-03 20:19 ` netfilter 01/08: xt_socket: make module available for INPUT chain Patrick McHardy
2009-12-03 20:19 ` netfilter 02/08: remove synchronize_net() calls in ip_queue/ip6_queue Patrick McHardy
2009-12-03 20:19 ` netfilter 03/08: nf_conntrack: avoid additional compare Patrick McHardy
2009-12-03 20:19 ` netfilter 04/08: nf_nat_helper: tidy up adjust_tcp_sequence Patrick McHardy
2009-12-03 20:19 ` netfilter 05/08: remove unneccessary checks from netlink notifiers Patrick McHardy
2009-12-03 20:19 ` netfilter 06/08: nf_ct_tcp: improve out-of-sync situation in TCP tracking Patrick McHardy
2009-12-03 20:19 ` Patrick McHardy [this message]
2009-12-03 20:19 ` netfilter 08/08: net/ipv[46]/netfilter: Move && and || to end of previous line Patrick McHardy
2009-12-03 21:00 ` netfilter 00/08: Netfilter Update David Miller
2009-12-03 21:24 ` David Miller
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=20091203201940.8831.2282.sendpatchset@x2.localnet \
--to=kaber@trash.net \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).