From: Stephen Hemminger <shemminger@osdl.org>
To: netdev@vger.kernel.org
Subject: IP fragmentation bug from NFS
Date: Fri, 22 Sep 2006 13:35:12 -0700 [thread overview]
Message-ID: <20060922133512.01a9e9d0@localhost.localdomain> (raw)
http://bugzilla.kernel.org/show_bug.cgi?id=7018
Looking at this, it seems that when NFS hands UDP a fragmented (non-linear skb),
it traps because it tries to trim bytes off a non-linear skb. Not sure if skb_trim
needs fixing, or IP is broken..
---
ssize_t ip_append_page(struct sock *sk, struct page *page,
int offset, size_t size, int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb;
struct rtable *rt;
struct ip_options *opt = NULL;
int hh_len;
int mtu;
int len;
int err;
unsigned int maxfraglen, fragheaderlen, fraggap;
if (inet->hdrincl)
return -EPERM;
if (flags&MSG_PROBE)
return 0;
if (skb_queue_empty(&sk->sk_write_queue))
return -EINVAL;
rt = inet->cork.rt;
if (inet->cork.flags & IPCORK_OPT)
opt = inet->cork.opt;
if (!(rt->u.dst.dev->features&NETIF_F_SG))
return -EOPNOTSUPP;
hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
mtu = inet->cork.fragsize;
fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
if (inet->cork.length + size > 0xFFFF - fragheaderlen) {
ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
return -EMSGSIZE;
}
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
return -EINVAL;
inet->cork.length += size;
if ((sk->sk_protocol == IPPROTO_UDP) &&
(rt->u.dst.dev->features & NETIF_F_UFO)) {
skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
}
while (size > 0) {
int i;
if (skb_is_gso(skb))
len = size;
else {
/* Check if the remaining data fits into current packet. */
len = mtu - skb->len;
if (len < size)
len = maxfraglen - skb->len;
}
if (len <= 0) {
struct sk_buff *skb_prev;
char *data;
struct iphdr *iph;
int alloclen;
skb_prev = skb;
fraggap = skb_prev->len - maxfraglen;
alloclen = fragheaderlen + hh_len + fraggap + 15;
skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
if (unlikely(!skb)) {
err = -ENOBUFS;
goto error;
}
/*
* Fill in the control structures
*/
skb->ip_summed = CHECKSUM_NONE;
skb->csum = 0;
skb_reserve(skb, hh_len);
/*
* Find where to start putting bytes.
*/
data = skb_put(skb, fragheaderlen + fraggap);
skb->nh.iph = iph = (struct iphdr *)data;
data += fragheaderlen;
skb->h.raw = data;
if (fraggap) {
skb->csum = skb_copy_and_csum_bits(
skb_prev, maxfraglen,
data, fraggap, 0);
skb_prev->csum = csum_sub(skb_prev->csum,
skb->csum);
-----> pskb_trim_unique(skb_prev, maxfraglen);
--
Stephen Hemminger <shemminger@osdl.org>
next reply other threads:[~2006-09-22 20:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-22 20:35 Stephen Hemminger [this message]
2006-09-22 20:50 ` IP fragmentation bug from NFS David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060922133512.01a9e9d0@localhost.localdomain \
--to=shemminger@osdl.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).