tcp: limit sk_rcvlowat by the maximum receive buffer
Subsystems (3)
PATCH 1/1 tcp: limit sk_rcvlowat by the maximum receive buffer
From: Soheil Hassas Yeganeh <[email protected]>
The user-provided value to setsockopt(SO_RCVLOWAT) can be larger than the maximum possible receive buffer. Such values mute POLLIN signals on the socket which can stall progress on the socket.
Limit the user-provided value to half of the maximum receive buffer, i.e., half of sk_rcvbuf when the receive buffer size is set by the user, or otherwise half of sysctl_tcp_rmem[2].
Fixes d1361840f8c5 ("tcp: fix SO_RCVLOWAT and RCVBUF autotuning")
Signed-off-by Soheil Hassas Yeganeh <[email protected]>
Signed-off-by Eric Dumazet <[email protected]>
Reviewed-by Neal Cardwell <[email protected]>
Acked-by Willem de Bruijn <[email protected]>
--- net/ipv4/tcp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
net/ipv4/tcp.c +7 -5
@@ -1694,6 +1694,13 @@ EXPORT_SYMBOL(tcp_peek_len);/* Make sure sk_rcvbuf is big enough to satisfy SO_RCVLOWAT hint */ int tcp_set_rcvlowat (struct sock *sk,int val) { +int cap; + +if (sk->sk_userlocks &SOCK_RCVBUF_LOCK ) + cap = sk->sk_rcvbuf >>1 ; +else + cap =sock_net (sk)->ipv4.sysctl_tcp_rmem[2 ] >>1 ; + val =min (val, cap); sk->sk_rcvlowat = val ? :1 ;/* Check if we need to signal EPOLLIN right now */
@@ -1702,12 +1709,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val)if (sk->sk_userlocks &SOCK_RCVBUF_LOCK )return 0 ; -/* val comes from user space and might be close to INT_MAX */ val <<=1 ; -if (val <0 ) - val =INT_MAX ; - - val =min (val,sock_net (sk)->ipv4.sysctl_tcp_rmem[2 ]);if (val > sk->sk_rcvbuf) { sk->sk_rcvbuf = val;tcp_sk (sk)->window_clamp =tcp_win_from_space (sk, val);
Signature · 1 line
2.18.0.rc1.242.g61856ae69a-goog