Netdev List
 help / color / mirror / Atom feed
From: mingming cao <mmc@linux.ibm.com>
To: netdev-bot+sashiko@kernel.org
Cc: netdev@vger.kernel.org, nnac123@linux.ibm.com,
	maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com,
	chleroy@kernel.org, ritesh.list@gmail.com, sshegde@linux.ibm.com,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@kernel.org,
	kuba@kernel.org, pabeni@redhat.com,
	linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	horms@kernel.org, davemarq@linux.ibm.com, bjking1@linux.ibm.com,
	brking@linux.vnet.ibm.com, tlfalcon@linux.vnet.ibm.com,
	jmaxwell37@gmail.com, zdai@us.ibm.com, marcelo.leitner@gmail.com,
	ksiva@linux.vnet.ibm.com
Subject: Re: [PATCH net-next v4 9/9] ibmveth: check headers in the RX large send and checksum helpers
Date: Tue, 13 Oct 2026 14:00:33 -0700	[thread overview]
Message-ID: <2363fbc6-7ad2-4dd1-8ebc-822c16471b25@linux.ibm.com> (raw)
In-Reply-To: <179187067525.434549.7404862779574164491@kernel.org>


On 10/12/26 10:51 PM, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 · Medium: 0 (1) · Low: 1
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] ibmveth_rx_mss_helper() (drivers/net/ethernet/ibm/ibmveth.c) now
>    sets gso_segs = DIV_ROUND_UP(ip_len - hdr_len, gso_size).
> - [Low] The kernel-doc of ibmveth_rx_mss_helper_test() says the helper
>    takes "gso_segs from the IP length" and refuses "Frames whose headers…
>
> Pre-existing issues:
> - [Medium] ibmveth_rx_csum_helper()
>    (drivers/net/ethernet/ibm/ibmveth.c:1530) seeds the TCP pseudo-header…
>
> --
>
> ibmveth: check headers in the RX large send and checksum helpers
>
> This adds bounds checks on the IP and TCP headers in
> ibmveth_rx_mss_helper() and ibmveth_rx_csum_helper(). The checks include a
> minimum IPv4 ihl and TCP doff, and IPv4 TCP fragments are refused. The large
> send helper now computes gso_segs from the IP length and clamps gso_size,
> and KUnit cases are added for both helpers.
>
>> diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
>> index 85e176d0ed321..1c2ac88c28ca3 100644
>> --- a/drivers/net/ethernet/ibm/ibmveth.c
>> +++ b/drivers/net/ethernet/ibm/ibmveth.c
> [ ... ]
>
>> @@ -1406,28 +1410,41 @@ static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt)
>>   	if (skb->protocol == htons(ETH_P_IP)) {
>>   		struct iphdr *iph = (struct iphdr *)skb->data;
>>   
>> +		if (skb_headlen(skb) < sizeof(*iph) || iph->ihl < 5)
>> +			return false;
>>   		if (iph->protocol == IPPROTO_TCP) {
>> +			/* only a whole datagram has a TCP header to segment */
>> +			if (ip_is_fragment(iph))
>> +				return false;
>>   			offset = iph->ihl * 4;
>> -			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
>> +			ip_len = ntohs(iph->tot_len);
>> +			gso_type = SKB_GSO_TCPV4;
> [ ... ]
>
>>   	tcph = (struct tcphdr *)(skb->data + offset);
>> +	if (skb_headlen(skb) < offset + sizeof(*tcph) || tcph->doff < 5 ||
>> +	    ip_len > skb_headlen(skb) || ip_len <= offset + tcph->doff * 4)
>> +		return false;
>> +	skb_shinfo(skb)->gso_type = gso_type;
>>   	if (lrg_pkt) {
>>   		skb_shinfo(skb)->gso_size = mss;
>>   	} else if (offset) {
>> @@ -1436,11 +1453,18 @@ static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt)
>>   	}
>>   
>>   	if (skb_shinfo(skb)->gso_size) {
>> +		/* chosen by the sending partition: at least the floor
>> +		 * virtio_net_hdr_to_skb() uses, and never GSO_BY_FRAGS
>> +		 */
>> +		skb_shinfo(skb)->gso_size =
>> +			clamp_t(u16, skb_shinfo(skb)->gso_size,
>> +				TCP_MIN_GSO_SIZE, GSO_BY_FRAGS - 1);
>>   		hdr_len = offset + tcph->doff * 4;
>>   		skb_shinfo(skb)->gso_segs =
>> -				DIV_ROUND_UP(skb->len - hdr_len,
>> +				DIV_ROUND_UP(ip_len - hdr_len,
>>   					     skb_shinfo(skb)->gso_size);
>>   	}
> [Severity: High]
>
> Can gso_segs here undercount the number of segments that actually get
> produced?

|Thanks for catching this. Agreed. |

> The only check of ip_len against the frame is ip_len > skb_headlen(skb).
> That means a frame much longer than its IP length is accepted, and nothing
> trims the skb to ip_len before napi_gro_receive().
>
> The commit message says the skb is not marked SKB_GSO_DODGY because
> gso_segs is computed here. That holds once ip_rcv_core() trims the skb to
> tot_len, on local delivery or routing. On the Trunk VEA forwarding paths
> (a bridge without br_netfilter, or OVS without conntrack), the skb is not
> trimmed.
>
> For example, a sending partition could:
>
>    - set iph->check = 0xffff
>    - put an MSS of 8 in tcph->check
>    - set tot_len = 100
>    - send a frame of about 9000 bytes
>
> The new checks pass (100 <= headlen, 100 > 40), so gso_segs becomes 8.
> tcp_gso_segment() or hardware TSO works on skb->len instead, which gives
> about 1120 segments.
>
> On egress, gso_features_check() compares the trusted gso_segs against the
> device limit:
>
> net/core/dev.c:gso_features_check() {
>      ...
> 	if (gso_segs > READ_ONCE(dev->gso_max_segs))
> 		return features & ~NETIF_F_GSO_MASK;
>      ...
> }
>
> Also, qdisc_pkt_len_segs_init() only recomputes gso_segs from skb->len for
> SKB_GSO_DODGY skbs.
>
> Would this let a TSO skb past the egress NIC's gso_max_segs? Would it also
> make the qdisc and BQL accounting too low?
>
> Before this patch, gso_segs was derived from skb->len, which matches what
> gets segmented. Any of these would avoid the mismatch:
>
>    - trim the skb to ip_len, for example with pskb_trim_rcsum()
>    - refuse large sends where skb_headlen(skb) != ip_len
>    - compute gso_segs from skb->len
>
> [ ... ]
>
>> @@ -1493,6 +1523,8 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb,
>>   	if (iph_proto == IPPROTO_TCP) {
>>   		struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen);
>>   
>> +		if (skb_headlen(skb) < iphlen + sizeof(*tcph))
>> +			goto bad_hdr;
>>   		if (tcph->check == 0x0000) {
>>   			/* Recompute TCP pseudo header checksum  */
>>   			tcphdrlen = skb->len - iphlen;
> [Severity: Medium]
>
> This isn't a bug introduced by this patch, but should the pseudo-header
> length in ibmveth_rx_csum_helper() come from the IP header rather than
> skb->len?
>
> The frame can have bytes past the end of the IP datagram, either Ethernet
> padding or trailing bytes that ibmveth_rx_mss_helper() still accepts when
> ip_len < skb_headlen(skb). If tcph->check is also 0, the seed is computed
> over the wrong length, and skb_partial_csum_set() then marks the skb
> CHECKSUM_PARTIAL.
>
> ip_rcv_core() and ip6_rcv_core() later trim the skb with pskb_trim_rcsum().
> For CHECKSUM_PARTIAL, that only checks where the checksum field is:
>
> net/core/skbuff.c:pskb_trim_rcsum_slow() {
>      ...
> 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
> 		int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
> 		int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
>
> 		if (offset + sizeof(__sum16) > hdlen)
> 			return -EINVAL;
> 	}
>      ...
> }
>
> The seed is left as it was.
>
> Could a forwarded packet then go out with a TCP checksum over the trimmed
> data but a pseudo-header for the untrimmed length? The final receiver
> would drop it.
>
> This patch moved the large send helper to the IP length. Would
> tot_len - ihl * 4, or the IPv6 payload_len, make sense here too?
>
> [ ... ]

|Yes, that makes sense. Since that behavior predates this series (from 
commit 66aa0678efc2), I'd prefer not to expand Patch 9 further and will 
handle that as a separate follow-up. |



>> @@ -2508,10 +2549,214 @@ static void ibmveth_rxq_harvest_buffer_test(struct kunit *test)
> [ ... ]
>
>> +	} else {
>> +		struct iphdr *iph = (struct iphdr *)skb->data;
>> +
>> +		skb->protocol = htons(ETH_P_IP);
>> +		iph->version = 4;
>> +		iph->ihl = 5;
>> +		iph->protocol = IPPROTO_TCP;
>> +		iph->tot_len = htons(len);
>> +	}
> [ ... ]
>
>> +/**
>> + * ibmveth_rx_mss_helper_test - unit test for ibmveth_rx_mss_helper
>> + * @test: pointer to kunit structure
>> + *
>> + * Large send frames get gso_size from the descriptor or the TCP checksum
>> + * field, clamped, and gso_segs from the IP length. Frames whose headers
>> + * do not fit, with no TCP payload within the IP length, or that are
>> + * IPv4 fragments, are refused and left without GSO.
>> + *
>> + * Return: void
>> + */
> [Severity: Low]
>
> This isn't a bug, but do any of the cases in ibmveth_rx_mss_helper_test()
> test "gso_segs from the IP length" or the "headers do not fit" refusal?
>
> ibmveth_test_tcp_skb() always sets tot_len (or 40 + payload_len) equal to
> skb->len. So in every accepted case, DIV_ROUND_UP(ip_len - hdr_len, ...)
> gives the same result as the old DIV_ROUND_UP(skb->len - hdr_len, ...).
> The only case with ip_len < skb->len is the padding case, and it is refused
> before gso_segs is computed.
>
> No mss helper case builds an skb shorter than sizeof(struct iphdr),
> sizeof(struct ipv6hdr), or offset + sizeof(struct tcphdr). So if gso_segs
> went back to skb->len, or those skb_headlen() checks were dropped from
> ibmveth_rx_mss_helper(), every expectation would still pass.
>
> Could cases be added for a tot_len smaller than the frame and for truncated
> headers? Otherwise, could the kernel-doc be narrowed to what is tested?


|We added the tot_len < frame length KUnit test case in v5. Truncated 
headers are already safely caught by the strict IP length / payload 
checks. v5 is posted here: 
https://lore.kernel.org/netdev/20261013182926.30417-1-mmc@linux.ibm.com/ 
Thanks, Mingming pw-bot: cr|



      reply	other threads:[~2026-10-13 21:00 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-12  5:05 [PATCH net-next v4 0/9] ibmveth: fix hangs, use-after-frees and netpoll races Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 1/9] ibmveth: fix netpoll races with RX replenish Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 2/9] ibmveth: do not close twice after a failed reopen Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 3/9] ibmveth: disable the reset work before unregister in remove Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 4/9] ibmveth: step past bad RX correlators instead of spinning or oopsing Mingming Cao
2026-10-13  5:51   ` netdev-bot+sashiko
2026-10-12  5:05 ` [PATCH net-next v4 5/9] ibmveth: release the pool kobjects when probe fails Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 6/9] ibmveth: return the error when set_channels cannot add TX queues Mingming Cao
2026-10-13  5:51   ` netdev-bot+sashiko
2026-10-12  5:05 ` [PATCH net-next v4 7/9] ibmveth: wait for in-flight transmits in ibmveth_close() Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 8/9] ibmveth: wait for the RX poll to return before freeing the RX queue Mingming Cao
2026-10-12  5:05 ` [PATCH net-next v4 9/9] ibmveth: check headers in the RX large send and checksum helpers Mingming Cao
2026-10-13  5:51   ` netdev-bot+sashiko
2026-10-13 21:00     ` mingming cao [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2363fbc6-7ad2-4dd1-8ebc-822c16471b25@linux.ibm.com \
    --to=mmc@linux.ibm.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=bjking1@linux.ibm.com \
    --cc=brking@linux.vnet.ibm.com \
    --cc=chleroy@kernel.org \
    --cc=davem@davemloft.net \
    --cc=davemarq@linux.ibm.com \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=jmaxwell37@gmail.com \
    --cc=ksiva@linux.vnet.ibm.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=marcelo.leitner@gmail.com \
    --cc=mpe@ellerman.id.au \
    --cc=netdev-bot+sashiko@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=nnac123@linux.ibm.com \
    --cc=npiggin@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=ritesh.list@gmail.com \
    --cc=sshegde@linux.ibm.com \
    --cc=tlfalcon@linux.vnet.ibm.com \
    --cc=zdai@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox