From: Greg Kroah-Hartman Date: Wed, 12 Jun 2024 12:55:21 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v4.19.316~129 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e72621724b0e334ee22a3f1c15cab5a8bd166209;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: mptcp-fix-full-tcp-keep-alive-support.patch --- diff --git a/queue-5.15/mptcp-fix-full-tcp-keep-alive-support.patch b/queue-5.15/mptcp-fix-full-tcp-keep-alive-support.patch new file mode 100644 index 00000000000..641a4dc7abd --- /dev/null +++ b/queue-5.15/mptcp-fix-full-tcp-keep-alive-support.patch @@ -0,0 +1,223 @@ +From bd11dc4fb969ec148e50cd87f88a78246dbc4d0b Mon Sep 17 00:00:00 2001 +From: "Matthieu Baerts (NGI0)" +Date: Mon, 13 May 2024 18:13:26 -0700 +Subject: mptcp: fix full TCP keep-alive support + +From: Matthieu Baerts (NGI0) + +commit bd11dc4fb969ec148e50cd87f88a78246dbc4d0b upstream. + +SO_KEEPALIVE support has been added a while ago, as part of a series +"adding SOL_SOCKET" support. To have a full control of this keep-alive +feature, it is important to also support TCP_KEEP* socket options at the +SOL_TCP level. + +Supporting them on the setsockopt() part is easy, it is just a matter of +remembering each value in the MPTCP sock structure, and calling +tcp_sock_set_keep*() helpers on each subflow. If the value is not +modified (0), calling these helpers will not do anything. For the +getsockopt() part, the corresponding value from the MPTCP sock structure +or the default one is simply returned. All of this is very similar to +other TCP_* socket options supported by MPTCP. + +It looks important for kernels supporting SO_KEEPALIVE, to also support +TCP_KEEP* options as well: some apps seem to (wrongly) consider that if +the former is supported, the latter ones will be supported as well. But +also, not having this simple and isolated change is preventing MPTCP +support in some apps, and libraries like GoLang [1]. This is why this +patch is seen as a fix. + +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/383 +Fixes: 1b3e7ede1365 ("mptcp: setsockopt: handle SO_KEEPALIVE and SO_PRIORITY") +Link: https://github.com/golang/go/issues/56539 [1] +Acked-by: Paolo Abeni +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Mat Martineau +Link: https://lore.kernel.org/r/20240514011335.176158-3-martineau@kernel.org +Signed-off-by: Jakub Kicinski +[ Conflicts in the same context, because commit 29b5e5ef8739 ("mptcp: + implement TCP_NOTSENT_LOWAT support") (new feature), commit + 013e3179dbd2 ("mptcp: fix rcv space initialization") (not backported + because of the various conflicts, and because the race fixed by this + commit "does not produce ill effects in practice"), and commit + 4f6e14bd19d6 ("mptcp: support TCP_CORK and TCP_NODELAY") are not in + this version. The adaptations done by 7f71a337b515 ("mptcp: cleanup + SOL_TCP handling") have been adapted to this case here. Also, + TCP_KEEPINTVL and TCP_KEEPCNT value had to be set without lock, the + same way it was done on TCP side prior commit 6fd70a6b4e6f ("tcp: set + TCP_KEEPINTVL locklessly") and commit 84485080cbc1 ("tcp: set + TCP_KEEPCNT locklessly"). ] +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.h | 3 + + net/mptcp/sockopt.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 118 insertions(+) + +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -250,6 +250,9 @@ struct mptcp_sock { + bool use_64bit_ack; /* Set when we received a 64-bit DSN */ + bool csum_enabled; + spinlock_t join_list_lock; ++ int keepalive_cnt; ++ int keepalive_idle; ++ int keepalive_intvl; + struct work_struct work; + struct sk_buff *ooo_last_skb; + struct rb_root out_of_order_queue; +--- a/net/mptcp/sockopt.c ++++ b/net/mptcp/sockopt.c +@@ -593,6 +593,60 @@ static int mptcp_setsockopt_sol_tcp_cong + return ret; + } + ++static int __tcp_sock_set_keepintvl(struct sock *sk, int val) ++{ ++ if (val < 1 || val > MAX_TCP_KEEPINTVL) ++ return -EINVAL; ++ ++ WRITE_ONCE(tcp_sk(sk)->keepalive_intvl, val * HZ); ++ ++ return 0; ++} ++ ++static int __tcp_sock_set_keepcnt(struct sock *sk, int val) ++{ ++ if (val < 1 || val > MAX_TCP_KEEPCNT) ++ return -EINVAL; ++ ++ /* Paired with READ_ONCE() in keepalive_probes() */ ++ WRITE_ONCE(tcp_sk(sk)->keepalive_probes, val); ++ ++ return 0; ++} ++ ++static int mptcp_setsockopt_set_val(struct mptcp_sock *msk, int max, ++ int (*set_val)(struct sock *, int), ++ int *msk_val, sockptr_t optval, ++ unsigned int optlen) ++{ ++ struct mptcp_subflow_context *subflow; ++ struct sock *sk = (struct sock *)msk; ++ int val, err; ++ ++ err = mptcp_get_int_option(msk, optval, optlen, &val); ++ if (err) ++ return err; ++ ++ lock_sock(sk); ++ mptcp_for_each_subflow(msk, subflow) { ++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ int ret; ++ ++ lock_sock(ssk); ++ ret = set_val(ssk, val); ++ err = err ? : ret; ++ release_sock(ssk); ++ } ++ ++ if (!err) { ++ *msk_val = val; ++ sockopt_seq_inc(msk); ++ } ++ release_sock(sk); ++ ++ return err; ++} ++ + static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname, + sockptr_t optval, unsigned int optlen) + { +@@ -601,6 +655,21 @@ static int mptcp_setsockopt_sol_tcp(stru + return -EOPNOTSUPP; + case TCP_CONGESTION: + return mptcp_setsockopt_sol_tcp_congestion(msk, optval, optlen); ++ case TCP_KEEPIDLE: ++ return mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPIDLE, ++ &tcp_sock_set_keepidle_locked, ++ &msk->keepalive_idle, ++ optval, optlen); ++ case TCP_KEEPINTVL: ++ return mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPINTVL, ++ &__tcp_sock_set_keepintvl, ++ &msk->keepalive_intvl, ++ optval, optlen); ++ case TCP_KEEPCNT: ++ return mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPCNT, ++ &__tcp_sock_set_keepcnt, ++ &msk->keepalive_cnt, ++ optval, optlen); + } + + return -EOPNOTSUPP; +@@ -667,9 +736,40 @@ out: + return ret; + } + ++static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval, ++ int __user *optlen, int val) ++{ ++ int len; ++ ++ if (get_user(len, optlen)) ++ return -EFAULT; ++ if (len < 0) ++ return -EINVAL; ++ ++ if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) { ++ unsigned char ucval = (unsigned char)val; ++ ++ len = 1; ++ if (put_user(len, optlen)) ++ return -EFAULT; ++ if (copy_to_user(optval, &ucval, 1)) ++ return -EFAULT; ++ } else { ++ len = min_t(unsigned int, len, sizeof(int)); ++ if (put_user(len, optlen)) ++ return -EFAULT; ++ if (copy_to_user(optval, &val, len)) ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, + char __user *optval, int __user *optlen) + { ++ struct sock *sk = (void *)msk; ++ + switch (optname) { + case TCP_ULP: + case TCP_CONGESTION: +@@ -677,6 +777,18 @@ static int mptcp_getsockopt_sol_tcp(stru + case TCP_CC_INFO: + return mptcp_getsockopt_first_sf_only(msk, SOL_TCP, optname, + optval, optlen); ++ case TCP_KEEPIDLE: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_idle ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_time) / HZ); ++ case TCP_KEEPINTVL: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_intvl ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_intvl) / HZ); ++ case TCP_KEEPCNT: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_cnt ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes)); + } + return -EOPNOTSUPP; + } +@@ -746,6 +858,9 @@ static void sync_socket_options(struct m + + if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops) + tcp_set_congestion_control(ssk, msk->ca_name, false, true); ++ tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle); ++ __tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl); ++ __tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt); + } + + static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk) diff --git a/queue-5.15/series b/queue-5.15/series index b534e5fede9..812db041ef8 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -344,3 +344,4 @@ io_uring-fail-nop-if-non-zero-op-flags-is-passed-in.patch afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch revert-drm-amdgpu-init-iommu-after-amdkfd-device-init.patch +mptcp-fix-full-tcp-keep-alive-support.patch