Re: Slab corruption mm3 + davem fixes

From: David S. Miller (davem@redhat.com)
Date: Sun May 11 2003 - 17:34:10 EST


On Sun, 2003-05-11 at 15:15, Andrew Morton wrote:
> "David S. Miller" <davem@redhat.com> wrote:
> >
> > On Sun, 2003-05-11 at 09:21, Ed Tomlinson wrote:
> > > I am also seeing this on 69-bk (as of Sunday morning)
> > ...
> > > On May 10, 2003 11:19 pm, Ed Tomlinson wrote:
> > > > I looked at my logs and found the following error in it. My kernel is
> > > > 69-mm3 with two davem fixes on it.
> > ...
> > > > May 10 22:41:06 oscar kernel: Call Trace:
> > > > May 10 22:41:06 oscar kernel: [__slab_error+30/32] __slab_error+0x1e/0x20
> > > > May 10 22:41:06 oscar kernel: [check_poison_obj+376/384]
> > > > check_poison_obj+0x178/0x180 May 10 22:41:06 oscar kernel:
> > > > [kmalloc+221/392] kmalloc+0xdd/0x188 May 10 22:41:06 oscar kernel:
> > > > [alloc_skb+64/240] alloc_skb+0x40/0xf0 May 10 22:41:06 oscar kernel:
> >
> > Yeah, more bugs in the NAT netfilter changes. Debugging this one
> > patch is becomming a full time job :-(
> >
> > This should fix it. Rusty, you're computing checksums and mangling
> > src/dst using header pointers potentially pointing to free'd skbs.
> >
>
> Did you mean to send a one megabyte diff?

Let's try this again, here is the correct patch :-)

-- 
David S. Miller <davem@redhat.com>

# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1105 -> 1.1106 # net/ipv4/netfilter/ip_nat_core.c 1.25 -> 1.26 # net/ipv4/netfilter/ip_fw_compat_masq.c 1.8 -> 1.9 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1106 # [NETFILTER]: Fix stale skb data pointer usage in ipv4 NAT. # -------------------------------------------- # diff -Nru a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c --- a/net/ipv4/netfilter/ip_fw_compat_masq.c Sun May 11 15:31:41 2003 +++ b/net/ipv4/netfilter/ip_fw_compat_masq.c Sun May 11 15:31:41 2003 @@ -35,16 +35,15 @@ unsigned int do_masquerade(struct sk_buff **pskb, const struct net_device *dev) { - struct iphdr *iph = (*pskb)->nh.iph; struct ip_nat_info *info; enum ip_conntrack_info ctinfo; struct ip_conntrack *ct; unsigned int ret; /* Sorry, only ICMP, TCP and UDP. */ - if (iph->protocol != IPPROTO_ICMP - && iph->protocol != IPPROTO_TCP - && iph->protocol != IPPROTO_UDP) + if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP + && (*pskb)->nh.iph->protocol != IPPROTO_TCP + && (*pskb)->nh.iph->protocol != IPPROTO_UDP) return NF_DROP; /* Feed it to connection tracking; in fact we're in NF_IP_FORWARD, @@ -68,7 +67,7 @@ /* Setup the masquerade, if not already */ if (!info->initialized) { u_int32_t newsrc; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->daddr } } }; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr } } }; struct rtable *rt; struct ip_nat_multi_range range; @@ -124,19 +123,18 @@ check_for_demasq(struct sk_buff **pskb) { struct ip_conntrack_tuple tuple; - struct iphdr *iph = (*pskb)->nh.iph; struct ip_conntrack_protocol *protocol; struct ip_conntrack_tuple_hash *h; enum ip_conntrack_info ctinfo; struct ip_conntrack *ct; int ret; - protocol = ip_ct_find_proto(iph->protocol); + protocol = ip_ct_find_proto((*pskb)->nh.iph->protocol); /* We don't feed packets to conntrack system unless we know they're part of an connection already established by an explicit masq command. */ - switch (iph->protocol) { + switch ((*pskb)->nh.iph->protocol) { case IPPROTO_ICMP: /* ICMP errors. */ ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING); @@ -146,12 +144,6 @@ server here (== DNAT). Do SNAT icmp manips in POST_ROUTING handling. */ if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { - /* FIXME: Remove once NAT handled non-linear. - */ - if (skb_is_nonlinear(*pskb) - && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - icmp_reply_translation(pskb, ct, NF_IP_PRE_ROUTING, CTINFO2DIR(ctinfo)); @@ -166,7 +158,7 @@ case IPPROTO_UDP: IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0); - if (!get_tuple(iph, *pskb, iph->ihl*4, &tuple, protocol)) { + if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) { if (net_ratelimit()) printk("ip_fw_compat_masq: Can't get tuple\n"); return NF_ACCEPT; diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c --- a/net/ipv4/netfilter/ip_nat_core.c Sun May 11 15:31:41 2003 +++ b/net/ipv4/netfilter/ip_nat_core.c Sun May 11 15:31:41 2003 @@ -717,10 +717,13 @@ iph = (void *)(*pskb)->data + iphdroff; /* Manipulate protcol part. */ - if (!find_nat_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4, + if (!find_nat_proto(proto)->manip_pkt(pskb, + iphdroff + iph->ihl*4, manip, maniptype)) return 0; + iph = (void *)(*pskb)->data + iphdroff; + if (maniptype == IP_NAT_MANIP_SRC) { iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip, iph->check); @@ -952,6 +955,8 @@ READ_UNLOCK(&ip_nat_lock); hdrlen = (*pskb)->nh.iph->ihl * 4; + + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; inside->icmp.checksum = 0; inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu May 15 2003 - 22:00:37 EST