BPF List
 help / color / mirror / Atom feed
* [PATCH net-next v2] tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path
@ 2026-07-23 21:42 Tejas Birajdar
  2026-07-24 21:42 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Tejas Birajdar @ 2026-07-23 21:42 UTC (permalink / raw)
  To: Eric Dumazet, Neal Cardwell, netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S . Miller, David Ahern, bpf,
	linux-kernel, Tejas Birajdar

BPF_SOCK_OPS_RWND_INIT lets a sockops BPF program pick the initial TCP
receive window, e.g. to advertise a larger window up front in environments
where that is known to be safe. Today it is only effective for the passive
(listener) side; on the active (connect) side the value is computed and
then silently discarded.

On the passive path tcp_openreq_init_rwin() inflates full_space when the
program returns a non-zero window, so tcp_select_initial_window() can offer
it:

	else if (full_space < (u64)rcv_wnd * mss)
		full_space = min_t(u64, (u64)rcv_wnd * mss, INT_MAX);

tcp_select_initial_window() only clamps the requested window *down* to the
available space, so without inflating the space first the BPF reply can
never raise the offered window above tcp_full_space(sk).

tcp_connect_init() calls tcp_rwnd_init_bpf() but never inflates full_space,
so on connect() the requested window is clamped back to tcp_full_space(sk)
(~64KB at the default rcvbuf) and the program's value is ignored.

Inflate full_space in tcp_connect_init() as well; tp->advmss is the mss the
listener path uses (both are tcp_mss_clamp(tp, dst_metric_advmss(dst))).
Read full_space after tcp_rwnd_init_bpf() so a program that also adjusts
SO_RCVBUF is still reflected. Compute the inflated value in u64 and clamp
to INT_MAX to avoid overflow (full_space is int, rcv_wnd is u32), and
apply the same overflow fix to the existing listener-side computation.

Fixes: 13d3b1ebe287 ("bpf: Support for setting initial receive window")
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Tejas Birajdar <tejasbirajdar@meta.com>
---
v2:
  - Do the inflated full_space arithmetic in u64 and clamp to INT_MAX to
    avoid overflow, and apply the same fix to the existing listener path
    in tcp_openreq_init_rwin().
  - Read full_space after tcp_rwnd_init_bpf() so a program that also raises
    SO_RCVBUF via bpf_setsockopt() is reflected in the offered window.
  - Re-ran the sockops BPF/RWND functional test and the full in-tree
    packetdrill regression suite on the revised code (details below).
v1: https://lore.kernel.org/netdev/20260722170033.2763794-1-tejasbirajdar@meta.com/

Functional test: a cgroup sockops BPF program returning
skops->reply = N for BPF_SOCK_OPS_RWND_INIT was attached to the
connecting socket and driven with packetdrill on the active-open
(connect) path (advmss 1460, negotiated wscale 8). The offered window on
the first post-handshake ACK now tracks the requested value:

  req_segs   offered window (bytes)   = req_segs * advmss
  256        373760
  1024       1495040  (~1.43 MB)
  4096       5980160  (~5.7 MB)

Without an attached program the window stays at the default (~262 KB);
before this patch the requested value was discarded on connect() and the
default was advertised regardless.

Regression: the in-tree tools/testing/selftests/net/packetdrill suite
(471 test cases across ipv4/ipv6/ipv4-mapped-ipv6) was run under
virtme-ng on this commit and on its parent; both produce an identical
pass/fail set, so this patch introduces no newly failing tests.

 net/ipv4/tcp_minisocks.c | 4 ++--
 net/ipv4/tcp_output.c    | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index ddc4b17a826b..f8c1123aba43 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -453,8 +453,8 @@ void tcp_openreq_init_rwin(struct request_sock *req,
 	rcv_wnd = tcp_rwnd_init_bpf((struct sock *)req);
 	if (rcv_wnd == 0)
 		rcv_wnd = dst_metric(dst, RTAX_INITRWND);
-	else if (full_space < rcv_wnd * mss)
-		full_space = rcv_wnd * mss;
+	else if (full_space < (u64)rcv_wnd * mss)
+		full_space = min_t(u64, (u64)rcv_wnd * mss, INT_MAX);
 
 	/* tcp_full_space because it is guaranteed to be the first packet */
 	tcp_select_initial_window(sk_listener, full_space,
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index d7c1444b5e30..ffa28c98c211 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -4103,6 +4103,7 @@ static void tcp_connect_init(struct sock *sk)
 	const struct dst_entry *dst = __sk_dst_get(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	__u8 rcv_wscale;
+	int full_space;
 	u16 user_mss;
 	u32 rcv_wnd;
 
@@ -4137,10 +4138,13 @@ static void tcp_connect_init(struct sock *sk)
 		WRITE_ONCE(tp->window_clamp, tcp_full_space(sk));
 
 	rcv_wnd = tcp_rwnd_init_bpf(sk);
+	full_space = tcp_full_space(sk);
 	if (rcv_wnd == 0)
 		rcv_wnd = dst_metric(dst, RTAX_INITRWND);
+	else if (full_space < (u64)rcv_wnd * tp->advmss)
+		full_space = min_t(u64, (u64)rcv_wnd * tp->advmss, INT_MAX);
 
-	tcp_select_initial_window(sk, tcp_full_space(sk),
+	tcp_select_initial_window(sk, full_space,
 				  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
 				  &tp->rcv_wnd,
 				  &tp->window_clamp,
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH net-next v2] tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path
  2026-07-23 21:42 [PATCH net-next v2] tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path Tejas Birajdar
@ 2026-07-24 21:42 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-07-24 21:42 UTC (permalink / raw)
  To: Tejas Birajdar; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [Medium] Incomplete fix for integer overflow when computing the initial receive window in tcp_select_initial_window().
--

--- Patch [1]: [PATCH net-next v2] tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path ---
commit 49a334daa027598fc715c7e2fdf73a1c1031f8be
Author: Tejas Birajdar <tejasbirajdar@meta.com>
Subject: tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path

This commit enables the BPF_SOCK_OPS_RWND_INIT hook to set the initial TCP
receive window on the active connect path, matching the behavior of the
passive listener path. It also attempts to prevent integer overflow by
computing the inflated space in 64-bit arithmetic and clamping to INT_MAX.

> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index d7c1444b5e304..ffa28c98c2118 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
[ ... ]
> @@ -4137,10 +4138,13 @@ static void tcp_connect_init(struct sock *sk)
>  		WRITE_ONCE(tp->window_clamp, tcp_full_space(sk));
>  
>  	rcv_wnd = tcp_rwnd_init_bpf(sk);
> +	full_space = tcp_full_space(sk);
>  	if (rcv_wnd == 0)
>  		rcv_wnd = dst_metric(dst, RTAX_INITRWND);
> +	else if (full_space < (u64)rcv_wnd * tp->advmss)
> +		full_space = min_t(u64, (u64)rcv_wnd * tp->advmss, INT_MAX);
>  
> -	tcp_select_initial_window(sk, tcp_full_space(sk),
> +	tcp_select_initial_window(sk, full_space,
>  				  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
>  				  &tp->rcv_wnd,
>  				  &tp->window_clamp,

[Severity: Medium]
This is a pre-existing issue, but does the initial receive window calculation
still overflow inside tcp_select_initial_window() despite the u64 promotion
done here?

When a BPF program returns a very large initial receive window value (for
example, > 2941760 when MSS is 1460), the value is passed as the init_rcv_wnd
parameter into tcp_select_initial_window().

Inside net/ipv4/tcp_output.c:tcp_select_initial_window():

    void tcp_select_initial_window(..., __u32 mss, ..., __u32 init_rcv_wnd)
    {
        ...
        if (init_rcv_wnd)
            *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
        ...
    }

Because both init_rcv_wnd and mss are 32-bit types, does this multiplication
overflow and wrap around to a small value? This collapses the offered initial
receive window and appears to completely bypass the u64 overflow protection
this patch aims to introduce.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260723214208.3655474-1-tejasbirajdar@meta.com?part=1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-24 21:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 21:42 [PATCH net-next v2] tcp: honor BPF_SOCK_OPS_RWND_INIT on the active connect path Tejas Birajdar
2026-07-24 21:42 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox