From 1e69ba3fa29b13fe5229d6e325aee91ae5abe298 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 27 Nov 2004 15:35:38 +0100 Subject: [NETFILTER]: Verify NAT manips have been applied before reversing them in icmp_reply_translation ICMP errors may be generated for packets that don't have all NAT manips applied yet. Verify manips have been applied before reversing them. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_conntrack_standalone.c | 1 + net/ipv4/netfilter/ip_nat_core.c | 36 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 2055fd40014f2..0ae9b16c1ee42 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -882,6 +882,7 @@ void need_ip_conntrack(void) EXPORT_SYMBOL(ip_conntrack_protocol_register); EXPORT_SYMBOL(ip_conntrack_protocol_unregister); +EXPORT_SYMBOL(ip_ct_get_tuple); EXPORT_SYMBOL(invert_tuplepr); EXPORT_SYMBOL(ip_conntrack_alter_reply); EXPORT_SYMBOL(ip_conntrack_destroyed); diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index cbd0924fc936d..9b533caddc5d6 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -813,6 +813,23 @@ do_bindings(struct ip_conntrack *ct, /* not reached */ } +static inline int tuple_src_equal_dst(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) +{ + if (t1->dst.protonum != t2->dst.protonum || t1->src.ip != t2->dst.ip) + return 0; + if (t1->dst.protonum != IPPROTO_ICMP) + return t1->src.u.all == t2->dst.u.all; + else { + struct ip_conntrack_tuple inv; + + /* ICMP tuples are asymetric */ + invert_tuplepr(&inv, t1); + return inv.src.u.all == t2->src.u.all && + inv.dst.u.all == t2->dst.u.all; + } +} + int icmp_reply_translation(struct sk_buff **pskb, struct ip_conntrack *conntrack, @@ -825,6 +842,7 @@ icmp_reply_translation(struct sk_buff **pskb, } *inside; unsigned int i; struct ip_nat_info *info = &conntrack->nat.info; + struct ip_conntrack_tuple *cttuple, innertuple; int hdrlen; if (!skb_ip_make_writable(pskb,(*pskb)->nh.iph->ihl*4+sizeof(*inside))) @@ -868,6 +886,13 @@ icmp_reply_translation(struct sk_buff **pskb, such addresses are not too uncommon, as Alan Cox points out) */ + if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 + + sizeof(struct icmphdr) + inside->ip.ihl*4, + &innertuple, + ip_ct_find_proto(inside->ip.protocol))) + return 0; + cttuple = &conntrack->tuplehash[dir].tuple; + READ_LOCK(&ip_nat_lock); for (i = 0; i < info->num_manips; i++) { DEBUGP("icmp_reply: manip %u dir %s hook %u\n", @@ -891,6 +916,17 @@ icmp_reply_translation(struct sk_buff **pskb, if (info->manips[i].hooknum != hooknum) continue; + /* ICMP errors may be generated locally for packets that + * don't have all NAT manips applied yet. Verify manips + * have been applied before reversing them */ + if (info->manips[i].maniptype == IP_NAT_MANIP_SRC) { + if (!tuple_src_equal_dst(cttuple, &innertuple)) + continue; + } else { + if (!tuple_src_equal_dst(&innertuple, cttuple)) + continue; + } + DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n", info->manips[i].maniptype == IP_NAT_MANIP_SRC ? "DST" : "SRC", NIPQUAD(info->manips[i].manip.ip), -- cgit 1.2.3-korg