]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jun 2024 12:55:21 +0000 (14:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jun 2024 12:55:21 +0000 (14:55 +0200)
added patches:
mptcp-fix-full-tcp-keep-alive-support.patch

queue-5.15/mptcp-fix-full-tcp-keep-alive-support.patch [new file with mode: 0644]
queue-5.15/series

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 (file)
index 0000000..641a4dc
--- /dev/null
@@ -0,0 +1,223 @@
+From bd11dc4fb969ec148e50cd87f88a78246dbc4d0b Mon Sep 17 00:00:00 2001
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Mon, 13 May 2024 18:13:26 -0700
+Subject: mptcp: fix full TCP keep-alive support
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+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 <pabeni@redhat.com>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Mat Martineau <martineau@kernel.org>
+Link: https://lore.kernel.org/r/20240514011335.176158-3-martineau@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ 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) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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)
index b534e5fede917d4477a8d04fd3806eb1af1b6bb9..812db041ef82976c040aeecc80a79b8c59fd8691 100644 (file)
@@ -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