From 716ea3a7aae3a2bfc44cb97b5419c1c9868c7bc9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 2 Apr 2007 20:19:53 -0700 Subject: [NET]: Move generic skbuff stuff from XFRM code to generic code Move generic skbuff stuff from XFRM code to generic code so that AF_RXRPC can use it too. The kdoc comments I've attached to the functions needs to be checked by whoever wrote them as I had to make some guesses about the workings of these functions. Signed-off-By: David Howells Signed-off-by: David S. Miller --- net/xfrm/xfrm_algo.c | 169 --------------------------------------------------- 1 file changed, 169 deletions(-) (limited to 'net/xfrm/xfrm_algo.c') diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index f373a8a7d9c8..6249a9405bb8 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -612,175 +612,6 @@ EXPORT_SYMBOL_GPL(skb_icv_walk); #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) -/* Looking generic it is not used in another places. */ - -int -skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) -{ - int start = skb_headlen(skb); - int i, copy = start - offset; - int elt = 0; - - if (copy > 0) { - if (copy > len) - copy = len; - sg[elt].page = virt_to_page(skb->data + offset); - sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg[elt].length = copy; - elt++; - if ((len -= copy) == 0) - return elt; - offset += copy; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - if (copy > len) - copy = len; - sg[elt].page = frag->page; - sg[elt].offset = frag->page_offset+offset-start; - sg[elt].length = copy; - elt++; - if (!(len -= copy)) - return elt; - offset += copy; - } - start = end; - } - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - elt += skb_to_sgvec(list, sg+elt, offset - start, copy); - if ((len -= copy) == 0) - return elt; - offset += copy; - } - start = end; - } - } - BUG_ON(len); - return elt; -} -EXPORT_SYMBOL_GPL(skb_to_sgvec); - -/* Check that skb data bits are writable. If they are not, copy data - * to newly created private area. If "tailbits" is given, make sure that - * tailbits bytes beyond current end of skb are writable. - * - * Returns amount of elements of scatterlist to load for subsequent - * transformations and pointer to writable trailer skb. - */ - -int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) -{ - int copyflag; - int elt; - struct sk_buff *skb1, **skb_p; - - /* If skb is cloned or its head is paged, reallocate - * head pulling out all the pages (pages are considered not writable - * at the moment even if they are anonymous). - */ - if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && - __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL) - return -ENOMEM; - - /* Easy case. Most of packets will go this way. */ - if (!skb_shinfo(skb)->frag_list) { - /* A little of trouble, not enough of space for trailer. - * This should not happen, when stack is tuned to generate - * good frames. OK, on miss we reallocate and reserve even more - * space, 128 bytes is fair. */ - - if (skb_tailroom(skb) < tailbits && - pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC)) - return -ENOMEM; - - /* Voila! */ - *trailer = skb; - return 1; - } - - /* Misery. We are in troubles, going to mincer fragments... */ - - elt = 1; - skb_p = &skb_shinfo(skb)->frag_list; - copyflag = 0; - - while ((skb1 = *skb_p) != NULL) { - int ntail = 0; - - /* The fragment is partially pulled by someone, - * this can happen on input. Copy it and everything - * after it. */ - - if (skb_shared(skb1)) - copyflag = 1; - - /* If the skb is the last, worry about trailer. */ - - if (skb1->next == NULL && tailbits) { - if (skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list || - skb_tailroom(skb1) < tailbits) - ntail = tailbits + 128; - } - - if (copyflag || - skb_cloned(skb1) || - ntail || - skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list) { - struct sk_buff *skb2; - - /* Fuck, we are miserable poor guys... */ - if (ntail == 0) - skb2 = skb_copy(skb1, GFP_ATOMIC); - else - skb2 = skb_copy_expand(skb1, - skb_headroom(skb1), - ntail, - GFP_ATOMIC); - if (unlikely(skb2 == NULL)) - return -ENOMEM; - - if (skb1->sk) - skb_set_owner_w(skb2, skb1->sk); - - /* Looking around. Are we still alive? - * OK, link new skb, drop old one */ - - skb2->next = skb1->next; - *skb_p = skb2; - kfree_skb(skb1); - skb1 = skb2; - } - elt++; - *trailer = skb1; - skb_p = &skb1->next; - } - - return elt; -} -EXPORT_SYMBOL_GPL(skb_cow_data); - void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) { if (tail != skb) { -- cgit From eefa3906283a2b60a6d02a2cda593a7d7d7946c5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 26 Apr 2007 00:44:22 -0700 Subject: [NET]: Clean up sk_buff walkers. I noticed recently that, in skb_checksum(), "offset" and "start" are essentially the same thing and have the same value throughout the function, despite being computed differently. Using a single variable allows some cleanups and makes the skb_checksum() function smaller, more readable, and presumably marginally faster. We appear to have many other "sk_buff walker" functions built on the exact same model, so the cleanup applies to them, too. Here is a list of the functions I found to be affected: net/appletalk/ddp.c:atalk_sum_skb() net/core/datagram.c:skb_copy_datagram_iovec() net/core/datagram.c:skb_copy_and_csum_datagram() net/core/skbuff.c:skb_copy_bits() net/core/skbuff.c:skb_store_bits() net/core/skbuff.c:skb_checksum() net/core/skbuff.c:skb_copy_and_csum_bit() net/core/user_dma.c:dma_skb_copy_datagram_iovec() net/xfrm/xfrm_algo.c:skb_icv_walk() net/xfrm/xfrm_algo.c:skb_to_sgvec() OTOH, I admit I'm a bit surprised, the cleanup is rather obvious so I'm really wondering if I am missing something. Can anyone please comment on this? Signed-off-by: Jean Delvare Signed-off-by: David S. Miller --- net/appletalk/ddp.c | 25 ++++------- net/core/datagram.c | 50 +++++++-------------- net/core/skbuff.c | 122 ++++++++++++++++++--------------------------------- net/core/user_dma.c | 25 ++++------- net/xfrm/xfrm_algo.c | 22 ++++------ 5 files changed, 86 insertions(+), 158 deletions(-) (limited to 'net/xfrm/xfrm_algo.c') diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index f6a92a0b7aa6..16eda21fb38c 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -937,11 +937,11 @@ static unsigned long atalk_sum_partial(const unsigned char *data, static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, int len, unsigned long sum) { - int start = skb_headlen(skb); + int end = skb_headlen(skb); int i, copy; /* checksum stuff in header space */ - if ( (copy = start - offset) > 0) { + if ((copy = end - offset) > 0) { if (copy > len) copy = len; sum = atalk_sum_partial(skb->data + offset, copy, sum); @@ -953,11 +953,9 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, /* checksum stuff in frags */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { u8 *vaddr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -965,36 +963,31 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_skb_frag(frag); - sum = atalk_sum_partial(vaddr + frag->page_offset + - offset - start, copy, sum); + sum = atalk_sum_partial(vaddr + frag->page_offset, + copy, sum); kunmap_skb_frag(vaddr); if (!(len -= copy)) return sum; offset += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - sum = atalk_sum_skb(list, offset - start, - copy, sum); + sum = atalk_sum_skb(list, 0, copy, sum); if ((len -= copy) == 0) return sum; offset += copy; } - start = end; } } diff --git a/net/core/datagram.c b/net/core/datagram.c index cb056f476126..e1afa7679445 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -247,8 +247,8 @@ EXPORT_SYMBOL(skb_kill_datagram); int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, struct iovec *to, int len) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; /* Copy header. */ if (copy > 0) { @@ -263,11 +263,9 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, /* Copy paged appendix. Hmm... why does this look so complicated? */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { int err; u8 *vaddr; @@ -277,8 +275,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap(page); - err = memcpy_toiovec(to, vaddr + frag->page_offset + - offset - start, copy); + err = memcpy_toiovec(to, vaddr + frag->page_offset, + copy); kunmap(page); if (err) goto fault; @@ -286,30 +284,24 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, return 0; offset += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_copy_datagram_iovec(list, - offset - start, - to, copy)) + if (skb_copy_datagram_iovec(list, 0, to, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; } - start = end; } } if (!len) @@ -323,9 +315,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 __user *to, int len, __wsum *csump) { - int start = skb_headlen(skb); + int end = skb_headlen(skb); int pos = 0; - int i, copy = start - offset; + int i, copy = end - offset; /* Copy header. */ if (copy > 0) { @@ -344,11 +336,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; int err = 0; @@ -360,8 +350,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, copy = len; vaddr = kmap(page); csum2 = csum_and_copy_to_user(vaddr + - frag->page_offset + - offset - start, + frag->page_offset, to, copy, 0, &err); kunmap(page); if (err) @@ -373,24 +362,20 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, to += copy; pos += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list=list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { __wsum csum2 = 0; if (copy > len) copy = len; - if (skb_copy_and_csum_datagram(list, - offset - start, + if (skb_copy_and_csum_datagram(list, 0, to, copy, &csum2)) goto fault; @@ -401,7 +386,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, to += copy; pos += copy; } - start = end; } } if (!len) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 142257307fa2..32f087b5233e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1045,13 +1045,13 @@ pull_pages: int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) { int i, copy; - int start = skb_headlen(skb); + int end = skb_headlen(skb); if (offset > (int)skb->len - len) goto fault; /* Copy header. */ - if ((copy = start - offset) > 0) { + if ((copy = end - offset) > 0) { if (copy > len) copy = len; skb_copy_from_linear_data_offset(skb, offset, to, copy); @@ -1062,11 +1062,9 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { u8 *vaddr; @@ -1075,8 +1073,8 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); memcpy(to, - vaddr + skb_shinfo(skb)->frags[i].page_offset+ - offset - start, copy); + vaddr + skb_shinfo(skb)->frags[i].page_offset, + copy); kunmap_skb_frag(vaddr); if ((len -= copy) == 0) @@ -1084,30 +1082,25 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) offset += copy; to += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_copy_bits(list, offset - start, - to, copy)) + if (skb_copy_bits(list, 0, to, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; to += copy; } - start = end; } } if (!len) @@ -1132,12 +1125,12 @@ fault: int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) { int i, copy; - int start = skb_headlen(skb); + int end = skb_headlen(skb); if (offset > (int)skb->len - len) goto fault; - if ((copy = start - offset) > 0) { + if ((copy = end - offset) > 0) { if (copy > len) copy = len; skb_copy_to_linear_data_offset(skb, offset, from, copy); @@ -1149,11 +1142,9 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + frag->size; + end = offset + frag->size; if ((copy = end - offset) > 0) { u8 *vaddr; @@ -1161,8 +1152,7 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) copy = len; vaddr = kmap_skb_frag(frag); - memcpy(vaddr + frag->page_offset + offset - start, - from, copy); + memcpy(vaddr + frag->page_offset, from, copy); kunmap_skb_frag(vaddr); if ((len -= copy) == 0) @@ -1170,30 +1160,25 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) offset += copy; from += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_store_bits(list, offset - start, - from, copy)) + if (skb_store_bits(list, 0, from, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; from += copy; } - start = end; } } if (!len) @@ -1210,8 +1195,8 @@ EXPORT_SYMBOL(skb_store_bits); __wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; int pos = 0; /* Checksum header. */ @@ -1226,11 +1211,9 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; u8 *vaddr; @@ -1239,8 +1222,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_skb_frag(frag); - csum2 = csum_partial(vaddr + frag->page_offset + - offset - start, copy, 0); + csum2 = csum_partial(vaddr + frag->page_offset, + copy, 0); kunmap_skb_frag(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) @@ -1248,31 +1231,26 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, offset += copy; pos += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { __wsum csum2; if (copy > len) copy = len; - csum2 = skb_checksum(list, offset - start, - copy, 0); + csum2 = skb_checksum(list, 0, copy, 0); csum = csum_block_add(csum, csum2, pos); if ((len -= copy) == 0) return csum; offset += copy; pos += copy; } - start = end; } } BUG_ON(len); @@ -1285,8 +1263,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, __wsum csum) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; int pos = 0; /* Copy header. */ @@ -1303,11 +1281,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; u8 *vaddr; @@ -1317,9 +1293,8 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, copy = len; vaddr = kmap_skb_frag(frag); csum2 = csum_partial_copy_nocheck(vaddr + - frag->page_offset + - offset - start, to, - copy, 0); + frag->page_offset, + to, copy, 0); kunmap_skb_frag(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) @@ -1328,7 +1303,6 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, to += copy; pos += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { @@ -1336,16 +1310,13 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, for (; list; list = list->next) { __wsum csum2; - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - csum2 = skb_copy_and_csum_bits(list, - offset - start, + csum2 = skb_copy_and_csum_bits(list, 0, to, copy, 0); csum = csum_block_add(csum, csum2, pos); if ((len -= copy) == 0) @@ -1354,7 +1325,6 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, to += copy; pos += copy; } - start = end; } } BUG_ON(len); @@ -2026,8 +1996,8 @@ void __init skb_init(void) int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; int elt = 0; if (copy > 0) { @@ -2043,45 +2013,39 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; if (copy > len) copy = len; sg[elt].page = frag->page; - sg[elt].offset = frag->page_offset+offset-start; + sg[elt].offset = frag->page_offset; sg[elt].length = copy; elt++; if (!(len -= copy)) return elt; offset += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - elt += skb_to_sgvec(list, sg+elt, offset - start, copy); + elt += skb_to_sgvec(list, sg+elt, 0, copy); if ((len -= copy) == 0) return elt; offset += copy; } - start = end; } } BUG_ON(len); diff --git a/net/core/user_dma.c b/net/core/user_dma.c index 0ad1cd57bc39..89241cdeea3f 100644 --- a/net/core/user_dma.c +++ b/net/core/user_dma.c @@ -49,8 +49,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, struct sk_buff *skb, int offset, struct iovec *to, size_t len, struct dma_pinned_list *pinned_list) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; dma_cookie_t cookie = 0; /* Copy header. */ @@ -69,11 +69,9 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, /* Copy paged appendix. Hmm... why does this look so complicated? */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; copy = end - offset; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -82,8 +80,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, if (copy > len) copy = len; - cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page, - frag->page_offset + offset - start, copy); + cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, + page, frag->page_offset, copy); if (cookie < 0) goto fault; len -= copy; @@ -91,25 +89,21 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, goto end; offset += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; copy = end - offset; if (copy > 0) { if (copy > len) copy = len; cookie = dma_skb_copy_datagram_iovec(chan, list, - offset - start, to, copy, - pinned_list); + 0, to, copy, pinned_list); if (cookie < 0) goto fault; len -= copy; @@ -117,7 +111,6 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, goto end; offset += copy; } - start = end; } } diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 6249a9405bb8..be529c4241a6 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -532,8 +532,8 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, int offset, int len, icv_update_fn_t icv_update) { - int start = skb_headlen(skb); - int i, copy = start - offset; + int end = skb_headlen(skb); + int i, copy = end - offset; int err; struct scatterlist sg; @@ -556,11 +556,9 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; + BUG_TRAP(len >= 0); - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; + end = offset + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -568,7 +566,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, copy = len; sg.page = frag->page; - sg.offset = frag->page_offset + offset-start; + sg.offset = frag->page_offset; sg.length = copy; err = icv_update(desc, &sg, copy); @@ -579,22 +577,19 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, return 0; offset += copy; } - start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); + BUG_TRAP(len >= 0); - end = start + list->len; + end = offset + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - err = skb_icv_walk(list, desc, offset-start, + err = skb_icv_walk(list, desc, 0, copy, icv_update); if (unlikely(err)) return err; @@ -602,7 +597,6 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, return 0; offset += copy; } - start = end; } } BUG_ON(len); -- cgit From 1a028e50729b85d0a038fad13daf0ee201a37454 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Apr 2007 15:21:23 -0700 Subject: [NET]: Revert sk_buff walker cleanups. This reverts eefa3906283a2b60a6d02a2cda593a7d7d7946c5 The simplification made in that change works with the assumption that the 'offset' parameter to these functions is always positive or zero, which is not true. It can be and often is negative in order to access SKB header values in front of skb->data. Signed-off-by: David S. Miller --- net/appletalk/ddp.c | 25 +++++++---- net/core/datagram.c | 50 ++++++++++++++------- net/core/skbuff.c | 122 +++++++++++++++++++++++++++++++++------------------ net/core/user_dma.c | 25 +++++++---- net/xfrm/xfrm_algo.c | 22 ++++++---- 5 files changed, 158 insertions(+), 86 deletions(-) (limited to 'net/xfrm/xfrm_algo.c') diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 16eda21fb38c..f6a92a0b7aa6 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -937,11 +937,11 @@ static unsigned long atalk_sum_partial(const unsigned char *data, static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, int len, unsigned long sum) { - int end = skb_headlen(skb); + int start = skb_headlen(skb); int i, copy; /* checksum stuff in header space */ - if ((copy = end - offset) > 0) { + if ( (copy = start - offset) > 0) { if (copy > len) copy = len; sum = atalk_sum_partial(skb->data + offset, copy, sum); @@ -953,9 +953,11 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, /* checksum stuff in frags */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { u8 *vaddr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -963,31 +965,36 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_skb_frag(frag); - sum = atalk_sum_partial(vaddr + frag->page_offset, - copy, sum); + sum = atalk_sum_partial(vaddr + frag->page_offset + + offset - start, copy, sum); kunmap_skb_frag(vaddr); if (!(len -= copy)) return sum; offset += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - sum = atalk_sum_skb(list, 0, copy, sum); + sum = atalk_sum_skb(list, offset - start, + copy, sum); if ((len -= copy) == 0) return sum; offset += copy; } + start = end; } } diff --git a/net/core/datagram.c b/net/core/datagram.c index e1afa7679445..cb056f476126 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -247,8 +247,8 @@ EXPORT_SYMBOL(skb_kill_datagram); int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, struct iovec *to, int len) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; /* Copy header. */ if (copy > 0) { @@ -263,9 +263,11 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, /* Copy paged appendix. Hmm... why does this look so complicated? */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { int err; u8 *vaddr; @@ -275,8 +277,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap(page); - err = memcpy_toiovec(to, vaddr + frag->page_offset, - copy); + err = memcpy_toiovec(to, vaddr + frag->page_offset + + offset - start, copy); kunmap(page); if (err) goto fault; @@ -284,24 +286,30 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, return 0; offset += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_copy_datagram_iovec(list, 0, to, copy)) + if (skb_copy_datagram_iovec(list, + offset - start, + to, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; } + start = end; } } if (!len) @@ -315,9 +323,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 __user *to, int len, __wsum *csump) { - int end = skb_headlen(skb); + int start = skb_headlen(skb); int pos = 0; - int i, copy = end - offset; + int i, copy = start - offset; /* Copy header. */ if (copy > 0) { @@ -336,9 +344,11 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; int err = 0; @@ -350,7 +360,8 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, copy = len; vaddr = kmap(page); csum2 = csum_and_copy_to_user(vaddr + - frag->page_offset, + frag->page_offset + + offset - start, to, copy, 0, &err); kunmap(page); if (err) @@ -362,20 +373,24 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, to += copy; pos += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list=list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { __wsum csum2 = 0; if (copy > len) copy = len; - if (skb_copy_and_csum_datagram(list, 0, + if (skb_copy_and_csum_datagram(list, + offset - start, to, copy, &csum2)) goto fault; @@ -386,6 +401,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, to += copy; pos += copy; } + start = end; } } if (!len) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 32f087b5233e..142257307fa2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1045,13 +1045,13 @@ pull_pages: int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) { int i, copy; - int end = skb_headlen(skb); + int start = skb_headlen(skb); if (offset > (int)skb->len - len) goto fault; /* Copy header. */ - if ((copy = end - offset) > 0) { + if ((copy = start - offset) > 0) { if (copy > len) copy = len; skb_copy_from_linear_data_offset(skb, offset, to, copy); @@ -1062,9 +1062,11 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { u8 *vaddr; @@ -1073,8 +1075,8 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); memcpy(to, - vaddr + skb_shinfo(skb)->frags[i].page_offset, - copy); + vaddr + skb_shinfo(skb)->frags[i].page_offset+ + offset - start, copy); kunmap_skb_frag(vaddr); if ((len -= copy) == 0) @@ -1082,25 +1084,30 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) offset += copy; to += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_copy_bits(list, 0, to, copy)) + if (skb_copy_bits(list, offset - start, + to, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; to += copy; } + start = end; } } if (!len) @@ -1125,12 +1132,12 @@ fault: int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) { int i, copy; - int end = skb_headlen(skb); + int start = skb_headlen(skb); if (offset > (int)skb->len - len) goto fault; - if ((copy = end - offset) > 0) { + if ((copy = start - offset) > 0) { if (copy > len) copy = len; skb_copy_to_linear_data_offset(skb, offset, from, copy); @@ -1142,9 +1149,11 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + frag->size; + end = start + frag->size; if ((copy = end - offset) > 0) { u8 *vaddr; @@ -1152,7 +1161,8 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) copy = len; vaddr = kmap_skb_frag(frag); - memcpy(vaddr + frag->page_offset, from, copy); + memcpy(vaddr + frag->page_offset + offset - start, + from, copy); kunmap_skb_frag(vaddr); if ((len -= copy) == 0) @@ -1160,25 +1170,30 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) offset += copy; from += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; - end = offset + list->len; + BUG_TRAP(start <= offset + len); + + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - if (skb_store_bits(list, 0, from, copy)) + if (skb_store_bits(list, offset - start, + from, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; from += copy; } + start = end; } } if (!len) @@ -1195,8 +1210,8 @@ EXPORT_SYMBOL(skb_store_bits); __wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; int pos = 0; /* Checksum header. */ @@ -1211,9 +1226,11 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + skb_shinfo(skb)->frags[i].size; + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; u8 *vaddr; @@ -1222,8 +1239,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_skb_frag(frag); - csum2 = csum_partial(vaddr + frag->page_offset, - copy, 0); + csum2 = csum_partial(vaddr + frag->page_offset + + offset - start, copy, 0); kunmap_skb_frag(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) @@ -1231,26 +1248,31 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, offset += copy; pos += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; - end = offset + list->len; + BUG_TRAP(start <= offset + len); + + end = start + list->len; if ((copy = end - offset) > 0) { __wsum csum2; if (copy > len) copy = len; - csum2 = skb_checksum(list, 0, copy, 0); + csum2 = skb_checksum(list, offset - start, + copy, 0); csum = csum_block_add(csum, csum2, pos); if ((len -= copy) == 0) return csum; offset += copy; pos += copy; } + start = end; } } BUG_ON(len); @@ -1263,8 +1285,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, __wsum csum) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; int pos = 0; /* Copy header. */ @@ -1281,9 +1303,11 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + skb_shinfo(skb)->frags[i].size; + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { __wsum csum2; u8 *vaddr; @@ -1293,8 +1317,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, copy = len; vaddr = kmap_skb_frag(frag); csum2 = csum_partial_copy_nocheck(vaddr + - frag->page_offset, - to, copy, 0); + frag->page_offset + + offset - start, to, + copy, 0); kunmap_skb_frag(vaddr); csum = csum_block_add(csum, csum2, pos); if (!(len -= copy)) @@ -1303,6 +1328,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, to += copy; pos += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { @@ -1310,13 +1336,16 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, for (; list; list = list->next) { __wsum csum2; - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - csum2 = skb_copy_and_csum_bits(list, 0, + csum2 = skb_copy_and_csum_bits(list, + offset - start, to, copy, 0); csum = csum_block_add(csum, csum2, pos); if ((len -= copy) == 0) @@ -1325,6 +1354,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, to += copy; pos += copy; } + start = end; } } BUG_ON(len); @@ -1996,8 +2026,8 @@ void __init skb_init(void) int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; int elt = 0; if (copy > 0) { @@ -2013,39 +2043,45 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; if (copy > len) copy = len; sg[elt].page = frag->page; - sg[elt].offset = frag->page_offset; + sg[elt].offset = frag->page_offset+offset-start; sg[elt].length = copy; elt++; if (!(len -= copy)) return elt; offset += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - elt += skb_to_sgvec(list, sg+elt, 0, copy); + elt += skb_to_sgvec(list, sg+elt, offset - start, copy); if ((len -= copy) == 0) return elt; offset += copy; } + start = end; } } BUG_ON(len); diff --git a/net/core/user_dma.c b/net/core/user_dma.c index 89241cdeea3f..0ad1cd57bc39 100644 --- a/net/core/user_dma.c +++ b/net/core/user_dma.c @@ -49,8 +49,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, struct sk_buff *skb, int offset, struct iovec *to, size_t len, struct dma_pinned_list *pinned_list) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; dma_cookie_t cookie = 0; /* Copy header. */ @@ -69,9 +69,11 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, /* Copy paged appendix. Hmm... why does this look so complicated? */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; copy = end - offset; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -80,8 +82,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, if (copy > len) copy = len; - cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, - page, frag->page_offset, copy); + cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page, + frag->page_offset + offset - start, copy); if (cookie < 0) goto fault; len -= copy; @@ -89,21 +91,25 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, goto end; offset += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; copy = end - offset; if (copy > 0) { if (copy > len) copy = len; cookie = dma_skb_copy_datagram_iovec(chan, list, - 0, to, copy, pinned_list); + offset - start, to, copy, + pinned_list); if (cookie < 0) goto fault; len -= copy; @@ -111,6 +117,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, goto end; offset += copy; } + start = end; } } diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index be529c4241a6..6249a9405bb8 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -532,8 +532,8 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, int offset, int len, icv_update_fn_t icv_update) { - int end = skb_headlen(skb); - int i, copy = end - offset; + int start = skb_headlen(skb); + int i, copy = start - offset; int err; struct scatterlist sg; @@ -556,9 +556,11 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_TRAP(len >= 0); + int end; - end = offset + skb_shinfo(skb)->frags[i].size; + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -566,7 +568,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, copy = len; sg.page = frag->page; - sg.offset = frag->page_offset; + sg.offset = frag->page_offset + offset-start; sg.length = copy; err = icv_update(desc, &sg, copy); @@ -577,19 +579,22 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, return 0; offset += copy; } + start = end; } if (skb_shinfo(skb)->frag_list) { struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list; list = list->next) { - BUG_TRAP(len >= 0); + int end; + + BUG_TRAP(start <= offset + len); - end = offset + list->len; + end = start + list->len; if ((copy = end - offset) > 0) { if (copy > len) copy = len; - err = skb_icv_walk(list, desc, 0, + err = skb_icv_walk(list, desc, offset-start, copy, icv_update); if (unlikely(err)) return err; @@ -597,6 +602,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, return 0; offset += copy; } + start = end; } } BUG_ON(len); -- cgit