Commit 1a028e50 authored by David S. Miller's avatar David S. Miller

[NET]: Revert sk_buff walker cleanups.

This reverts eefa3906

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: default avatarDavid S. Miller <davem@davemloft.net>
parent 50f732ee
...@@ -937,11 +937,11 @@ static unsigned long atalk_sum_partial(const unsigned char *data, ...@@ -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, static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
int len, unsigned long sum) int len, unsigned long sum)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy; int i, copy;
/* checksum stuff in header space */ /* checksum stuff in header space */
if ((copy = end - offset) > 0) { if ( (copy = start - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
sum = atalk_sum_partial(skb->data + offset, copy, sum); 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, ...@@ -953,9 +953,11 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
/* checksum stuff in frags */ /* checksum stuff in frags */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 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) { if ((copy = end - offset) > 0) {
u8 *vaddr; u8 *vaddr;
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 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, ...@@ -963,31 +965,36 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
if (copy > len) if (copy > len)
copy = len; copy = len;
vaddr = kmap_skb_frag(frag); vaddr = kmap_skb_frag(frag);
sum = atalk_sum_partial(vaddr + frag->page_offset, sum = atalk_sum_partial(vaddr + frag->page_offset +
copy, sum); offset - start, copy, sum);
kunmap_skb_frag(vaddr); kunmap_skb_frag(vaddr);
if (!(len -= copy)) if (!(len -= copy))
return sum; return sum;
offset += copy; offset += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
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) if ((len -= copy) == 0)
return sum; return sum;
offset += copy; offset += copy;
} }
start = end;
} }
} }
......
...@@ -247,8 +247,8 @@ EXPORT_SYMBOL(skb_kill_datagram); ...@@ -247,8 +247,8 @@ EXPORT_SYMBOL(skb_kill_datagram);
int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
struct iovec *to, int len) struct iovec *to, int len)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
/* Copy header. */ /* Copy header. */
if (copy > 0) { if (copy > 0) {
...@@ -263,9 +263,11 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, ...@@ -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? */ /* Copy paged appendix. Hmm... why does this look so complicated? */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 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) { if ((copy = end - offset) > 0) {
int err; int err;
u8 *vaddr; u8 *vaddr;
...@@ -275,8 +277,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, ...@@ -275,8 +277,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
if (copy > len) if (copy > len)
copy = len; copy = len;
vaddr = kmap(page); vaddr = kmap(page);
err = memcpy_toiovec(to, vaddr + frag->page_offset, err = memcpy_toiovec(to, vaddr + frag->page_offset +
copy); offset - start, copy);
kunmap(page); kunmap(page);
if (err) if (err)
goto fault; goto fault;
...@@ -284,24 +286,30 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, ...@@ -284,24 +286,30 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
return 0; return 0;
offset += copy; offset += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
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; goto fault;
if ((len -= copy) == 0) if ((len -= copy) == 0)
return 0; return 0;
offset += copy; offset += copy;
} }
start = end;
} }
} }
if (!len) if (!len)
...@@ -315,9 +323,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, ...@@ -315,9 +323,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
u8 __user *to, int len, u8 __user *to, int len,
__wsum *csump) __wsum *csump)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int pos = 0; int pos = 0;
int i, copy = end - offset; int i, copy = start - offset;
/* Copy header. */ /* Copy header. */
if (copy > 0) { if (copy > 0) {
...@@ -336,9 +344,11 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, ...@@ -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++) { 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) { if ((copy = end - offset) > 0) {
__wsum csum2; __wsum csum2;
int err = 0; int err = 0;
...@@ -350,7 +360,8 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, ...@@ -350,7 +360,8 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
copy = len; copy = len;
vaddr = kmap(page); vaddr = kmap(page);
csum2 = csum_and_copy_to_user(vaddr + csum2 = csum_and_copy_to_user(vaddr +
frag->page_offset, frag->page_offset +
offset - start,
to, copy, 0, &err); to, copy, 0, &err);
kunmap(page); kunmap(page);
if (err) if (err)
...@@ -362,20 +373,24 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, ...@@ -362,20 +373,24 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
to += copy; to += copy;
pos += copy; pos += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list=list->next) { 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 = end - offset) > 0) {
__wsum csum2 = 0; __wsum csum2 = 0;
if (copy > len) if (copy > len)
copy = len; copy = len;
if (skb_copy_and_csum_datagram(list, 0, if (skb_copy_and_csum_datagram(list,
offset - start,
to, copy, to, copy,
&csum2)) &csum2))
goto fault; goto fault;
...@@ -386,6 +401,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, ...@@ -386,6 +401,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
to += copy; to += copy;
pos += copy; pos += copy;
} }
start = end;
} }
} }
if (!len) if (!len)
......
...@@ -1045,13 +1045,13 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) ...@@ -1045,13 +1045,13 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta)
int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
{ {
int i, copy; int i, copy;
int end = skb_headlen(skb); int start = skb_headlen(skb);
if (offset > (int)skb->len - len) if (offset > (int)skb->len - len)
goto fault; goto fault;
/* Copy header. */ /* Copy header. */
if ((copy = end - offset) > 0) { if ((copy = start - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
skb_copy_from_linear_data_offset(skb, offset, to, copy); 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) ...@@ -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++) { 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) { if ((copy = end - offset) > 0) {
u8 *vaddr; u8 *vaddr;
...@@ -1073,8 +1075,8 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) ...@@ -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]); vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
memcpy(to, memcpy(to,
vaddr + skb_shinfo(skb)->frags[i].page_offset, vaddr + skb_shinfo(skb)->frags[i].page_offset+
copy); offset - start, copy);
kunmap_skb_frag(vaddr); kunmap_skb_frag(vaddr);
if ((len -= copy) == 0) if ((len -= copy) == 0)
...@@ -1082,25 +1084,30 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) ...@@ -1082,25 +1084,30 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
offset += copy; offset += copy;
to += copy; to += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
if (skb_copy_bits(list, 0, to, copy)) if (skb_copy_bits(list, offset - start,
to, copy))
goto fault; goto fault;
if ((len -= copy) == 0) if ((len -= copy) == 0)
return 0; return 0;
offset += copy; offset += copy;
to += copy; to += copy;
} }
start = end;
} }
} }
if (!len) if (!len)
...@@ -1125,12 +1132,12 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) ...@@ -1125,12 +1132,12 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
{ {
int i, copy; int i, copy;
int end = skb_headlen(skb); int start = skb_headlen(skb);
if (offset > (int)skb->len - len) if (offset > (int)skb->len - len)
goto fault; goto fault;
if ((copy = end - offset) > 0) { if ((copy = start - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
skb_copy_to_linear_data_offset(skb, offset, from, copy); 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) ...@@ -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++) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->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) { if ((copy = end - offset) > 0) {
u8 *vaddr; u8 *vaddr;
...@@ -1152,7 +1161,8 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) ...@@ -1152,7 +1161,8 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
copy = len; copy = len;
vaddr = kmap_skb_frag(frag); 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); kunmap_skb_frag(vaddr);
if ((len -= copy) == 0) if ((len -= copy) == 0)
...@@ -1160,25 +1170,30 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) ...@@ -1160,25 +1170,30 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
offset += copy; offset += copy;
from += copy; from += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
if (skb_store_bits(list, 0, from, copy)) if (skb_store_bits(list, offset - start,
from, copy))
goto fault; goto fault;
if ((len -= copy) == 0) if ((len -= copy) == 0)
return 0; return 0;
offset += copy; offset += copy;
from += copy; from += copy;
} }
start = end;
} }
} }
if (!len) if (!len)
...@@ -1195,8 +1210,8 @@ EXPORT_SYMBOL(skb_store_bits); ...@@ -1195,8 +1210,8 @@ EXPORT_SYMBOL(skb_store_bits);
__wsum skb_checksum(const struct sk_buff *skb, int offset, __wsum skb_checksum(const struct sk_buff *skb, int offset,
int len, __wsum csum) int len, __wsum csum)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
int pos = 0; int pos = 0;
/* Checksum header. */ /* Checksum header. */
...@@ -1211,9 +1226,11 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, ...@@ -1211,9 +1226,11 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
} }
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 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) { if ((copy = end - offset) > 0) {
__wsum csum2; __wsum csum2;
u8 *vaddr; u8 *vaddr;
...@@ -1222,8 +1239,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, ...@@ -1222,8 +1239,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
if (copy > len) if (copy > len)
copy = len; copy = len;
vaddr = kmap_skb_frag(frag); vaddr = kmap_skb_frag(frag);
csum2 = csum_partial(vaddr + frag->page_offset, csum2 = csum_partial(vaddr + frag->page_offset +
copy, 0); offset - start, copy, 0);
kunmap_skb_frag(vaddr); kunmap_skb_frag(vaddr);
csum = csum_block_add(csum, csum2, pos); csum = csum_block_add(csum, csum2, pos);
if (!(len -= copy)) if (!(len -= copy))
...@@ -1231,26 +1248,31 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, ...@@ -1231,26 +1248,31 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
offset += copy; offset += copy;
pos += copy; pos += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
__wsum csum2; __wsum csum2;
if (copy > len) if (copy > len)
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); csum = csum_block_add(csum, csum2, pos);
if ((len -= copy) == 0) if ((len -= copy) == 0)
return csum; return csum;
offset += copy; offset += copy;
pos += copy; pos += copy;
} }
start = end;
} }
} }
BUG_ON(len); BUG_ON(len);
...@@ -1263,8 +1285,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, ...@@ -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, __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
u8 *to, int len, __wsum csum) u8 *to, int len, __wsum csum)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
int pos = 0; int pos = 0;
/* Copy header. */ /* Copy header. */
...@@ -1281,9 +1303,11 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ...@@ -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++) { 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) { if ((copy = end - offset) > 0) {
__wsum csum2; __wsum csum2;
u8 *vaddr; u8 *vaddr;
...@@ -1293,8 +1317,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ...@@ -1293,8 +1317,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
copy = len; copy = len;
vaddr = kmap_skb_frag(frag); vaddr = kmap_skb_frag(frag);
csum2 = csum_partial_copy_nocheck(vaddr + csum2 = csum_partial_copy_nocheck(vaddr +
frag->page_offset, frag->page_offset +
to, copy, 0); offset - start, to,
copy, 0);
kunmap_skb_frag(vaddr); kunmap_skb_frag(vaddr);
csum = csum_block_add(csum, csum2, pos); csum = csum_block_add(csum, csum2, pos);
if (!(len -= copy)) if (!(len -= copy))
...@@ -1303,6 +1328,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ...@@ -1303,6 +1328,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
to += copy; to += copy;
pos += copy; pos += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
...@@ -1310,13 +1336,16 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ...@@ -1310,13 +1336,16 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
for (; list; list = list->next) { for (; list; list = list->next) {
__wsum csum2; __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 = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
csum2 = skb_copy_and_csum_bits(list, 0, csum2 = skb_copy_and_csum_bits(list,
offset - start,
to, copy, 0); to, copy, 0);
csum = csum_block_add(csum, csum2, pos); csum = csum_block_add(csum, csum2, pos);
if ((len -= copy) == 0) if ((len -= copy) == 0)
...@@ -1325,6 +1354,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ...@@ -1325,6 +1354,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
to += copy; to += copy;
pos += copy; pos += copy;
} }
start = end;
} }
} }
BUG_ON(len); BUG_ON(len);
...@@ -1996,8 +2026,8 @@ void __init skb_init(void) ...@@ -1996,8 +2026,8 @@ void __init skb_init(void)
int int
skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
int elt = 0; int elt = 0;
if (copy > 0) { if (copy > 0) {
...@@ -2013,39 +2043,45 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) ...@@ -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++) { 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) { if ((copy = end - offset) > 0) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
if (copy > len) if (copy > len)
copy = len; copy = len;
sg[elt].page = frag->page; sg[elt].page = frag->page;
sg[elt].offset = frag->page_offset; sg[elt].offset = frag->page_offset+offset-start;
sg[elt].length = copy; sg[elt].length = copy;
elt++; elt++;
if (!(len -= copy)) if (!(len -= copy))
return elt; return elt;
offset += copy; offset += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
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) if ((len -= copy) == 0)
return elt; return elt;
offset += copy; offset += copy;
} }
start = end;
} }
} }
BUG_ON(len); BUG_ON(len);
......
...@@ -49,8 +49,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, ...@@ -49,8 +49,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
struct sk_buff *skb, int offset, struct iovec *to, struct sk_buff *skb, int offset, struct iovec *to,
size_t len, struct dma_pinned_list *pinned_list) size_t len, struct dma_pinned_list *pinned_list)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
dma_cookie_t cookie = 0; dma_cookie_t cookie = 0;
/* Copy header. */ /* Copy header. */
...@@ -69,9 +69,11 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, ...@@ -69,9 +69,11 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
/* Copy paged appendix. Hmm... why does this look so complicated? */ /* Copy paged appendix. Hmm... why does this look so complicated? */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 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; copy = end - offset;
if ((copy = end - offset) > 0) { if ((copy = end - offset) > 0) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
...@@ -80,8 +82,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, ...@@ -80,8 +82,8 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
if (copy > len) if (copy > len)
copy = len; copy = len;
cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page,
page, frag->page_offset, copy); frag->page_offset + offset - start, copy);
if (cookie < 0) if (cookie < 0)
goto fault; goto fault;
len -= copy; len -= copy;
...@@ -89,21 +91,25 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, ...@@ -89,21 +91,25 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
goto end; goto end;
offset += copy; offset += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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; copy = end - offset;
if (copy > 0) { if (copy > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
cookie = dma_skb_copy_datagram_iovec(chan, list, cookie = dma_skb_copy_datagram_iovec(chan, list,
0, to, copy, pinned_list); offset - start, to, copy,
pinned_list);
if (cookie < 0) if (cookie < 0)
goto fault; goto fault;
len -= copy; len -= copy;
...@@ -111,6 +117,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, ...@@ -111,6 +117,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
goto end; goto end;
offset += copy; offset += copy;
} }
start = end;
} }
} }
......
...@@ -532,8 +532,8 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); ...@@ -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 skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
int offset, int len, icv_update_fn_t icv_update) int offset, int len, icv_update_fn_t icv_update)
{ {
int end = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = end - offset; int i, copy = start - offset;
int err; int err;
struct scatterlist sg; struct scatterlist sg;
...@@ -556,9 +556,11 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, ...@@ -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++) { 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) { if ((copy = end - offset) > 0) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 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, ...@@ -566,7 +568,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
copy = len; copy = len;
sg.page = frag->page; sg.page = frag->page;
sg.offset = frag->page_offset; sg.offset = frag->page_offset + offset-start;
sg.length = copy; sg.length = copy;
err = icv_update(desc, &sg, copy); err = icv_update(desc, &sg, copy);
...@@ -577,19 +579,22 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, ...@@ -577,19 +579,22 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
return 0; return 0;
offset += copy; offset += copy;
} }
start = end;
} }
if (skb_shinfo(skb)->frag_list) { if (skb_shinfo(skb)->frag_list) {
struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list; list = list->next) { 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 = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
err = skb_icv_walk(list, desc, 0, err = skb_icv_walk(list, desc, offset-start,
copy, icv_update); copy, icv_update);
if (unlikely(err)) if (unlikely(err))
return err; return err;
...@@ -597,6 +602,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, ...@@ -597,6 +602,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
return 0; return 0;
offset += copy; offset += copy;
} }
start = end;
} }
} }
BUG_ON(len); BUG_ON(len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment