diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2005-07-21 13:14:46 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-07-21 13:14:46 -0700 |
commit | 4acdbdbe5089c06d5e0c7e96783fcc4414ded00a (patch) | |
tree | 77629aef70bd92983518b6f5dd13c70a222c4cbb /net/ipv4/netfilter/ip_conntrack_ftp.c | |
parent | 4aa49d130df9209707a97786a55a3f584b7345e9 (diff) |
[NETFILTER]: ip_conntrack_expect_related must not free expectation
If a connection tracking helper tells us to expect a connection, and
we're already expecting that connection, we simply free the one they
gave us and return success.
The problem is that NAT helpers (eg. FTP) have to allocate the
expectation first (to see what port is available) then rewrite the
packet. If that rewrite fails, they try to remove the expectation,
but it was freed in ip_conntrack_expect_related.
This is one example of a larger problem: having registered the
expectation, the pointer is no longer ours to use. Reference counting
is needed for ctnetlink anyway, so introduce it now.
To have a single "put" path, we need to grab the reference to the
connection on creation, rather than open-coding it in the caller.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/netfilter/ip_conntrack_ftp.c')
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_ftp.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index fea6dd2a00b..7a3b773be3f 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -376,7 +376,7 @@ static int help(struct sk_buff **pskb, fb_ptr + matchoff, matchlen, ntohl(th->seq) + matchoff); /* Allocate expectation which will be inserted */ - exp = ip_conntrack_expect_alloc(); + exp = ip_conntrack_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; @@ -403,8 +403,7 @@ static int help(struct sk_buff **pskb, networks, or the packet filter itself). */ if (!loose) { ret = NF_ACCEPT; - ip_conntrack_expect_free(exp); - goto out_update_nl; + goto out_put_expect; } exp->tuple.dst.ip = htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]); @@ -419,7 +418,6 @@ static int help(struct sk_buff **pskb, { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); exp->expectfn = NULL; - exp->master = ct; /* Now, NAT might want to mangle the packet, and register the * (possibly changed) expectation itself. */ @@ -428,13 +426,15 @@ static int help(struct sk_buff **pskb, matchoff, matchlen, exp, &seq); else { /* Can't expect this? Best to drop packet now. */ - if (ip_conntrack_expect_related(exp) != 0) { - ip_conntrack_expect_free(exp); + if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; - } else + else ret = NF_ACCEPT; } +out_put_expect: + ip_conntrack_expect_put(exp); + out_update_nl: /* Now if this ends in \n, update ftp info. Seq may have been * adjusted by NAT code. */ |