|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH net-next 02/15] net: skbuff: add skb_checksum_full() that reports failure
On Mon, Oct 19, 2026 at 6:50 AM Josef Bacik <josef@xxxxxxxxxxxxxx> wrote:
>
> skb_checksum() can't fail. When the range runs into unreadable frags
> or past the end of the skb it returns 0, which is also a valid
> checksum, so its callers can't tell the sum from a failure. For the
> receive-side validation helpers that means a packet whose payload was
> never checksummed can pass, and commit 20ddd0fd2fcd ("net: skbuff:
> don't BUG() on leftover length in skb_checksum() and friends") made the
> past-the-end case one of those instead of a BUG().
>
> Add skb_checksum_full(), which adds the range's sum to *@csump and
> returns 0, or returns -EFAULT for unreadable frags or a range past the
> end of the skb, and -EINVAL for a negative length, leaving *@csump
> alone. It's __must_check so a caller can't ignore the failure, and it
> recurses into frag_list members through itself so a failure there
> isn't lost either.
>
> skb_checksum() becomes a wrapper around it that behaves as before for
> the callers that haven't been converted: it returns 0 on failure and
> warns once if that was because of unreadable frags. The following
> patches convert the core users, and the rest will follow per subsystem.
>
Is it possible to stop sending 1 large series where some patches are
related and some patches are not? Are the changes for segmentation in
this series related to checksumming?
> Assisted-by: LLM
> Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
> ---
> include/linux/skbuff.h | 2 ++
> net/core/skbuff.c | 56
> +++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 48 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 09db32f70b53..969b1c3269ec 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -4279,6 +4279,8 @@ 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 __must_check skb_copy_and_csum_bits(const struct sk_buff *skb, int
> offset,
> u8 *to, int len, __wsum *csum);
> +int __must_check skb_checksum_full(const struct sk_buff *skb, int offset,
> + int len, __wsum *csump);
> int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int
> offset,
> struct pipe_inode_info *pipe, unsigned int len,
> unsigned int flags);
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index a2b52a5a61a9..061c61422a38 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -3545,12 +3545,31 @@ int skb_store_bits(struct sk_buff *skb, int offset,
> const void *from, int len)
> EXPORT_SYMBOL(skb_store_bits);
>
> /* Checksum skb data. */
> -__wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum
> csum)
> +/**
> + * skb_checksum_full - checksum a range of an skb
> + * @skb: buffer to checksum
> + * @offset: offset in @skb to start at
> + * @len: number of bytes to checksum
> + * @csump: the sum to add to; on success the range's sum is added to it
> + *
> + * Return: 0 on success, -EINVAL if @len is negative, or -EFAULT if @skb
> + * has unreadable frags in the range or runs out before @len does. On
> + * failure *@csump is not changed.
> + */
> +int skb_checksum_full(const struct sk_buff *skb, int offset, int len,
> + __wsum *csump)
> {
> int start = skb_headlen(skb);
> int i, copy = start - offset;
> struct sk_buff *frag_iter;
> + __wsum csum = *csump;
Check for reverse christmas tree.
> int pos = 0;
> + int err;
> +
> + if (unlikely(len < 0)) {
> + DEBUG_NET_WARN_ON_ONCE(1);
> + return -EINVAL;
> + }
We don't normally go for these defensive checks.
--
Thanks,
Mina
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |