diff mbox series

[net,v2] net: tighten bad gso csum offset check in virtio_net_hdr

Message ID 20240910213553.839926-1-willemdebruijn.kernel@gmail.com (mailing list archive)
State Accepted
Commit 6513eb3d3191574b58859ef2d6dc26c0277c6f81
Delegated to: Netdev Maintainers
Headers show
Series [net,v2] net: tighten bad gso csum offset check in virtio_net_hdr | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 16 this patch: 16
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 3 maintainers not CCed: xuanzhuo@linux.alibaba.com virtualization@lists.linux.dev eperezma@redhat.com
netdev/build_clang success Errors and warnings before: 16 this patch: 16
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 18 this patch: 18
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 9 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-09-12--00-00 (tests: 764)

Commit Message

Willem de Bruijn Sept. 10, 2024, 9:35 p.m. UTC
From: Willem de Bruijn <willemb@google.com>

The referenced commit drops bad input, but has false positives.
Tighten the check to avoid these.

The check detects illegal checksum offload requests, which produce
csum_start/csum_off beyond end of packet after segmentation.

But it is based on two incorrect assumptions:

1. virtio_net_hdr_to_skb with VIRTIO_NET_HDR_GSO_TCP[46] implies GSO.
True in callers that inject into the tx path, such as tap.
But false in callers that inject into rx, like virtio-net.
Here, the flags indicate GRO, and CHECKSUM_UNNECESSARY or
CHECKSUM_NONE without VIRTIO_NET_HDR_F_NEEDS_CSUM is normal.

2. TSO requires checksum offload, i.e., ip_summed == CHECKSUM_PARTIAL.
False, as tcp[46]_gso_segment will fix up csum_start and offset for
all other ip_summed by calling __tcp_v4_send_check.

Because of 2, we can limit the scope of the fix to virtio_net_hdr
that do try to set these fields, with a bogus value.

Link: https://lore.kernel.org/netdev/20240909094527.GA3048202@port70.net/
Fixes: 89add40066f9 ("net: drop bad gso csum_start and offset in virtio_net_hdr")
Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Cc: stable@vger.kernel.org

---

Changes v1->v2:
- Fix Cc:
- Add Acks from v1
---
 include/linux/virtio_net.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

patchwork-bot+netdevbpf@kernel.org Sept. 12, 2024, 3:50 a.m. UTC | #1
Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 10 Sep 2024 17:35:35 -0400 you wrote:
> From: Willem de Bruijn <willemb@google.com>
> 
> The referenced commit drops bad input, but has false positives.
> Tighten the check to avoid these.
> 
> The check detects illegal checksum offload requests, which produce
> csum_start/csum_off beyond end of packet after segmentation.
> 
> [...]

Here is the summary with links:
  - [net,v2] net: tighten bad gso csum offset check in virtio_net_hdr
    https://git.kernel.org/netdev/net/c/6513eb3d3191

You are awesome, thank you!
Sudeep Holla Sept. 12, 2024, 1:39 p.m. UTC | #2
On Tue, Sep 10, 2024 at 05:35:35PM -0400, Willem de Bruijn wrote:
> From: Willem de Bruijn <willemb@google.com>
> 
> The referenced commit drops bad input, but has false positives.
> Tighten the check to avoid these.
> 
> The check detects illegal checksum offload requests, which produce
> csum_start/csum_off beyond end of packet after segmentation.
> 
> But it is based on two incorrect assumptions:
> 
> 1. virtio_net_hdr_to_skb with VIRTIO_NET_HDR_GSO_TCP[46] implies GSO.
> True in callers that inject into the tx path, such as tap.
> But false in callers that inject into rx, like virtio-net.
> Here, the flags indicate GRO, and CHECKSUM_UNNECESSARY or
> CHECKSUM_NONE without VIRTIO_NET_HDR_F_NEEDS_CSUM is normal.
> 
> 2. TSO requires checksum offload, i.e., ip_summed == CHECKSUM_PARTIAL.
> False, as tcp[46]_gso_segment will fix up csum_start and offset for
> all other ip_summed by calling __tcp_v4_send_check.
> 
> Because of 2, we can limit the scope of the fix to virtio_net_hdr
> that do try to set these fields, with a bogus value.
>

I see it is already queued and extremely sorry for not testing and getting
back earlier. Good news: it does fix the issue in my setup(same as reported
at [1])

So, FWIW,

Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Willem de Bruijn Sept. 12, 2024, 3:30 p.m. UTC | #3
Sudeep Holla wrote:
> On Tue, Sep 10, 2024 at 05:35:35PM -0400, Willem de Bruijn wrote:
> > From: Willem de Bruijn <willemb@google.com>
> > 
> > The referenced commit drops bad input, but has false positives.
> > Tighten the check to avoid these.
> > 
> > The check detects illegal checksum offload requests, which produce
> > csum_start/csum_off beyond end of packet after segmentation.
> > 
> > But it is based on two incorrect assumptions:
> > 
> > 1. virtio_net_hdr_to_skb with VIRTIO_NET_HDR_GSO_TCP[46] implies GSO.
> > True in callers that inject into the tx path, such as tap.
> > But false in callers that inject into rx, like virtio-net.
> > Here, the flags indicate GRO, and CHECKSUM_UNNECESSARY or
> > CHECKSUM_NONE without VIRTIO_NET_HDR_F_NEEDS_CSUM is normal.
> > 
> > 2. TSO requires checksum offload, i.e., ip_summed == CHECKSUM_PARTIAL.
> > False, as tcp[46]_gso_segment will fix up csum_start and offset for
> > all other ip_summed by calling __tcp_v4_send_check.
> > 
> > Because of 2, we can limit the scope of the fix to virtio_net_hdr
> > that do try to set these fields, with a bogus value.
> >
> 
> I see it is already queued and extremely sorry for not testing and getting
> back earlier. Good news: it does fix the issue in my setup(same as reported
> at [1])
> 
> So, FWIW,
> 
> Tested-by: Sudeep Holla <sudeep.holla@arm.com>

That is great to hear. Thanks for reporting your results, Sudeep.
diff mbox series

Patch

diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 6c395a2600e8d..276ca543ef44d 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -173,7 +173,8 @@  static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 			break;
 		case SKB_GSO_TCPV4:
 		case SKB_GSO_TCPV6:
-			if (skb->csum_offset != offsetof(struct tcphdr, check))
+			if (skb->ip_summed == CHECKSUM_PARTIAL &&
+			    skb->csum_offset != offsetof(struct tcphdr, check))
 				return -EINVAL;
 			break;
 		}