Skip to content

Commit 52cbd23

Browse files
wdebruijkuba-moo
authored andcommitted
udp: fix skb_copy_and_csum_datagram with odd segment sizes
When iteratively computing a checksum with csum_block_add, track the offset "pos" to correctly rotate in csum_block_add when offset is odd. The open coded implementation of skb_copy_and_csum_datagram did this. With the switch to __skb_datagram_iter calling csum_and_copy_to_iter, pos was reinitialized to 0 on each call. Bring back the pos by passing it along with the csum to the callback. Changes v1->v2 - pass csum value, instead of csump pointer (Alexander Duyck) Link: https://lore.kernel.org/netdev/20210128152353.GB27281@optiplex/ Fixes: 950fcae ("datagram: consolidate datagram copy to iter helpers") Reported-by: Oliver Graute <oliver.graute@gmail.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Alexander Duyck <alexanderduyck@fb.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://lore.kernel.org/r/20210203192952.1849843-1-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 1d23a56 commit 52cbd23

File tree

3 files changed

+31
-13
lines changed

3 files changed

+31
-13
lines changed

include/linux/uio.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,13 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
260260
{
261261
i->count = count;
262262
}
263-
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csump, struct iov_iter *i);
263+
264+
struct csum_state {
265+
__wsum csum;
266+
size_t off;
267+
};
268+
269+
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csstate, struct iov_iter *i);
264270
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
265271
bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
266272
size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,

lib/iov_iter.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -592,14 +592,15 @@ static __wsum csum_and_memcpy(void *to, const void *from, size_t len,
592592
}
593593

594594
static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
595-
__wsum *csum, struct iov_iter *i)
595+
struct csum_state *csstate,
596+
struct iov_iter *i)
596597
{
597598
struct pipe_inode_info *pipe = i->pipe;
598599
unsigned int p_mask = pipe->ring_size - 1;
600+
__wsum sum = csstate->csum;
601+
size_t off = csstate->off;
599602
unsigned int i_head;
600603
size_t n, r;
601-
size_t off = 0;
602-
__wsum sum = *csum;
603604

604605
if (!sanity(i))
605606
return 0;
@@ -621,7 +622,8 @@ static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
621622
i_head++;
622623
} while (n);
623624
i->count -= bytes;
624-
*csum = sum;
625+
csstate->csum = sum;
626+
csstate->off = off;
625627
return bytes;
626628
}
627629

@@ -1522,18 +1524,19 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum,
15221524
}
15231525
EXPORT_SYMBOL(csum_and_copy_from_iter_full);
15241526

1525-
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csump,
1527+
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *_csstate,
15261528
struct iov_iter *i)
15271529
{
1530+
struct csum_state *csstate = _csstate;
15281531
const char *from = addr;
1529-
__wsum *csum = csump;
15301532
__wsum sum, next;
1531-
size_t off = 0;
1533+
size_t off;
15321534

15331535
if (unlikely(iov_iter_is_pipe(i)))
1534-
return csum_and_copy_to_pipe_iter(addr, bytes, csum, i);
1536+
return csum_and_copy_to_pipe_iter(addr, bytes, _csstate, i);
15351537

1536-
sum = *csum;
1538+
sum = csstate->csum;
1539+
off = csstate->off;
15371540
if (unlikely(iov_iter_is_discard(i))) {
15381541
WARN_ON(1); /* for now */
15391542
return 0;
@@ -1561,7 +1564,8 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csump,
15611564
off += v.iov_len;
15621565
})
15631566
)
1564-
*csum = sum;
1567+
csstate->csum = sum;
1568+
csstate->off = off;
15651569
return bytes;
15661570
}
15671571
EXPORT_SYMBOL(csum_and_copy_to_iter);

net/core/datagram.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,8 +721,16 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
721721
struct iov_iter *to, int len,
722722
__wsum *csump)
723723
{
724-
return __skb_datagram_iter(skb, offset, to, len, true,
725-
csum_and_copy_to_iter, csump);
724+
struct csum_state csdata = { .csum = *csump };
725+
int ret;
726+
727+
ret = __skb_datagram_iter(skb, offset, to, len, true,
728+
csum_and_copy_to_iter, &csdata);
729+
if (ret)
730+
return ret;
731+
732+
*csump = csdata.csum;
733+
return 0;
726734
}
727735

728736
/**

0 commit comments

Comments
 (0)