From 61ce9d0c60b28afe8bdf32038130b1a2b2a04119 Mon Sep 17 00:00:00 2001 From: t_jeang Date: Tue, 6 Jan 2009 12:06:05 +0000 Subject: [PATCH] imported patch debug-dump-skb-info-when-invalid --- include/linux/skbuff.h | 2 + net/core/skbuff.c | 84 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cc82c016..bbb681c1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1630,5 +1630,7 @@ static inline int skb_is_gso(const struct sk_buff *skb) return skb_shinfo(skb)->gso_size; } +extern void skb_dump_info(const struct sk_buff *skb); + #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 05c69085..1db8ce88 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -66,10 +66,74 @@ #include #include +#include static kmem_cache_t *skbuff_head_cache __read_mostly; static kmem_cache_t *skbuff_fclone_cache __read_mostly; +void skb_dump_info(const struct sk_buff *skb) +{ +#ifdef CONFIG_XEN + int i, nr = skb_shinfo(skb)->nr_frags; +#endif + struct ethhdr *ethh = eth_hdr(skb); + + printk(KERN_ERR "skb: skb at %p with %d users\n", skb, atomic_read(&skb->users)); + printk(KERN_ERR "skb: prev %p next %p prev->next %p next->prev %p\n", + skb->prev, skb->next, + skb->prev ? skb->prev->next : NULL, + skb->next ? skb->next->prev : NULL); + printk(KERN_ERR "skb: len is %#x (data:%#x mac:%#x) truesize %#x\n", + skb->len, skb->data_len, skb->mac_len, skb->truesize); + + printk(KERN_ERR "skb: linear:%s\n", skb_is_nonlinear(skb) ? "No" : "Yes"); + printk(KERN_ERR "skb: data %p head %p tail %p end %p\n", + skb->data, skb->head, skb->tail, skb->end); + printk(KERN_ERR "skb: flags are local_df:%d cloned:%d ip_summed:%d nohdr:%d\n", + skb->local_df, skb->cloned, skb->ip_summed, skb->nohdr); + printk(KERN_ERR "skb: nfctinfo:%d pkt_type:%d fclone:%d ipvs_property:%d\n", + skb->nfctinfo, skb->pkt_type, skb->nohdr, skb->ipvs_property); +#ifdef CONFIG_XEN + printk(KERN_ERR "skb: proto_data_valid:%d proto_csum_blank:%d\n", + skb->proto_data_valid, skb->proto_csum_blank); +#endif + printk(KERN_ERR "skb: shared info %p ref %#x\n", skb_shinfo(skb), atomic_read(&skb_shinfo(skb)->dataref)); + printk(KERN_ERR "skb: frag_list %p\n", skb_shinfo(skb)->frag_list); + + printk(KERN_ERR "skb: eth: (%p) src:%02x:%02x:%02x:%02x:%02x:%02x dest:%02x:%02x:%02x:%02x:%02x:%02x proto %u\n", + ethh, + ethh->h_source[0], ethh->h_source[1], ethh->h_source[2], ethh->h_source[3], ethh->h_source[4], ethh->h_source[5], + ethh->h_dest[0], ethh->h_dest[1], ethh->h_dest[2], ethh->h_dest[3], ethh->h_dest[4], ethh->h_dest[5], + ntohs(ethh->h_proto)); + if (ethh->h_proto == __constant_htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + printk(KERN_ERR "skb: ip: (%p) saddr "NIPQUAD_FMT" daddr "NIPQUAD_FMT" protocol %d frag_off %d\n", + iph, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), iph->protocol, iph->frag_off); + + if (iph->protocol == IPPROTO_TCP) { + struct tcphdr *tcph = tcp_hdr(skb); + printk(KERN_ERR "bnx2: tcp: (%p) source %d dest %d seq %u ack %u\n", + tcph, ntohs(tcph->source), ntohs(tcph->dest), ntohl(tcph->seq), ntohl(tcph->ack_seq)); + } + } + +#ifdef CONFIG_XEN + for(i=0; ifrags[i]; + unsigned long pfn = page_to_pfn(frag->page); + unsigned long mfn = pfn_to_mfn(pfn); + printk(KERN_ERR "skb: %d/%d page:%p offset:%#x size:%#x virt:%p pfn:%#lx mfn:%#lx%s flags:%lx%s)\n", + i, nr, frag->page, frag->page_offset, frag->size, + phys_to_virt(page_to_phys(frag->page)), pfn, mfn, + phys_to_machine_mapping_valid(pfn) ? "" : "(BAD)", + frag->page->flags, + PageForeign(frag->page) ? "FOREIGN" : "not-foreign"); + } +#endif +} +EXPORT_SYMBOL(skb_dump_info); + + /* * Keep out-of-line to prevent kernel bloat. * __builtin_return_address is not used because it is not always @@ -1340,13 +1404,20 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, int start = skb_headlen(skb); int i, copy = start - offset; int pos = 0; + int src_err = 0; /* Copy header. */ if (copy > 0) { if (copy > len) copy = len; - csum = csum_partial_copy_nocheck(skb->data + offset, to, - copy, csum); + csum = csum_partial_copy_generic(skb->data + offset, to, + copy, csum, &src_err, NULL); + if (src_err) { + skb_dump_info(skb); + printk(KERN_CRIT "checksum: CA-22751 bad skb in head\n"); + BUG(); + } + if ((len -= copy) == 0) return csum; offset += copy; @@ -1368,10 +1439,15 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_skb_frag(frag); - csum2 = csum_partial_copy_nocheck(vaddr + + csum2 = csum_partial_copy_generic(vaddr + frag->page_offset + offset - start, to, - copy, 0); + copy, 0, &src_err, NULL); + if (src_err) { + skb_dump_info(skb); + printk(KERN_CRIT "checksum: CA-22751 bad skb in frag %d\n", i); + BUG(); + } kunmap_skb_frag(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) -- 2.39.5