[PATCH 2.6.10 1/1] netfilter: fix crash on nat+icmp packets
From: mukesh agrawal
Date: Tue Mar 01 2005 - 20:43:45 EST
This patch fixes a kernel crashing bug when using NAT. The crash occurs in
the case when we send out a UDP packet to a closed port on another host,
with the UDP packet being SNATed. The remote host replies with an ICMP
port unreachable (type 3, code 3). We need to adjust the ICMP packet,
because the UDP packet was SNATed.
The cause of the crash is that udp_manip_pkt reads *pskb into iph before
calling skb_ip_make_writable, and fails to update iph after the call.
Since skb_ip_make_writable may delete the original skb when it makes a
copy, a page fault may occur when udp_manip_pkt later dereferences iph.
I suspect that normally, the relevant skbuff holds a UDP packet, and
either the skbuff is unshared (so no copy is made, and the skbuff
remains valid), or is shared, but remains so while udp_manip_pkt is
running (and hence, the old reference to the skbuff is still okay).
When we get an ICMP reply for a SNATed UDP packet, ip_nat_proto_udp is
asked to modify the UDP header inside the payload of the ICMP packet. (The
call chain is ip_nat_fn -> icmp_reply_translation -> ip_nat_manip_pkt ->
udp_manip_pkt.)
Since the UDP header is beyond the ICMP header, skb_ip_make_writable
copies the skbuff, and deletes the original. Then udp_manip_pkt's iph is
invalid, and dereferencing it causes a page fault.
Glancing at the code for tcp_manip_pkt, I think it would have the same
problem, but I haven't tested that case. The patch below fixes the UDP
case only.
(For the record, my kernel tree also has the tproxy patch from
http://www.balabit.com/downloads/tproxy/linux-2.4/cttproxy-2.6.10-2.0.0.tar.gz
applied. But I think this bug is independent of that patch.)
diff -uprN linux-2.6.10.orig/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.10.fixed/net/ipv4/netfilter/ip_nat_proto_udp.c
--- linux-2.6.10.orig/net/ipv4/netfilter/ip_nat_proto_udp.c 2004-12-24 16:34:01.000000000 -0500
+++ linux-2.6.10.fixed/net/ipv4/netfilter/ip_nat_proto_udp.c 2005-03-01 19:32:21.000000000 -0500
@@ -95,6 +95,9 @@ udp_manip_pkt(struct sk_buff **pskb,
if (!skb_ip_make_writable(pskb, hdroff + sizeof(hdr)))
return 0;
+ /* skb_ip_make_writable may have copied the skb, and deleted
+ the original */
+ iph = (struct iphdr *)((*pskb)->data + iphdroff);
hdr = (void *)(*pskb)->data + hdroff;
if (maniptype == IP_NAT_MANIP_SRC) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/