]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Aug 2025 09:12:02 +0000 (11:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Aug 2025 09:12:02 +0000 (11:12 +0200)
added patches:
nfsd-avoid-ref-leak-in-nfsd_open_local_fh.patch
nfsd-don-t-set-the-ctime-on-delegated-atime-updates.patch
sunrpc-fix-handling-of-server-side-tls-alerts.patch

queue-6.16/nfsd-avoid-ref-leak-in-nfsd_open_local_fh.patch [new file with mode: 0644]
queue-6.16/nfsd-don-t-set-the-ctime-on-delegated-atime-updates.patch [new file with mode: 0644]
queue-6.16/pwm-rockchip-round-period-duty-down-on-apply-up-on-g.patch [deleted file]
queue-6.16/sched-do-not-call-__put_task_struct-on-rt-if-pi_bloc.patch [deleted file]
queue-6.16/series
queue-6.16/sunrpc-fix-handling-of-server-side-tls-alerts.patch [new file with mode: 0644]

diff --git a/queue-6.16/nfsd-avoid-ref-leak-in-nfsd_open_local_fh.patch b/queue-6.16/nfsd-avoid-ref-leak-in-nfsd_open_local_fh.patch
new file mode 100644 (file)
index 0000000..c97d649
--- /dev/null
@@ -0,0 +1,50 @@
+From e5a73150776f18547ee685c9f6bfafe549714899 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neil@brown.name>
+Date: Fri, 18 Jul 2025 11:26:14 +1000
+Subject: nfsd: avoid ref leak in nfsd_open_local_fh()
+
+From: NeilBrown <neil@brown.name>
+
+commit e5a73150776f18547ee685c9f6bfafe549714899 upstream.
+
+If two calls to nfsd_open_local_fh() race and both successfully call
+nfsd_file_acquire_local(), they will both get an extra reference to the
+net to accompany the file reference stored in *pnf.
+
+One of them will fail to store (using xchg()) the file reference in
+*pnf and will drop that reference but WON'T drop the accompanying
+reference to the net.  This leak means that when the nfs server is shut
+down it will hang in nfsd_shutdown_net() waiting for
+&nn->nfsd_net_free_done.
+
+This patch adds the missing nfsd_net_put().
+
+Reported-by: Mike Snitzer <snitzer@kernel.org>
+Fixes: e6f7e1487ab5 ("nfs_localio: simplify interface to nfsd for getting nfsd_file")
+Cc: stable@vger.kernel.org
+Signed-off-by: NeilBrown <neil@brown.name>
+Tested-by: Mike Snitzer <snitzer@kernel.org>
+Reviewed-by: Mike Snitzer <snitzer@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/localio.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/nfsd/localio.c
++++ b/fs/nfsd/localio.c
+@@ -103,10 +103,11 @@ nfsd_open_local_fh(struct net *net, stru
+                       if (nfsd_file_get(new) == NULL)
+                               goto again;
+                       /*
+-                       * Drop the ref we were going to install and the
+-                       * one we were going to return.
++                       * Drop the ref we were going to install (both file and
++                       * net) and the one we were going to return (only file).
+                        */
+                       nfsd_file_put(localio);
++                      nfsd_net_put(net);
+                       nfsd_file_put(localio);
+                       localio = new;
+               }
diff --git a/queue-6.16/nfsd-don-t-set-the-ctime-on-delegated-atime-updates.patch b/queue-6.16/nfsd-don-t-set-the-ctime-on-delegated-atime-updates.patch
new file mode 100644 (file)
index 0000000..4c3fa50
--- /dev/null
@@ -0,0 +1,57 @@
+From f9a348e0de19226fc3c7e81de7677d3fa2c4b2d8 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 16 Jul 2025 09:34:29 -0400
+Subject: nfsd: don't set the ctime on delegated atime updates
+
+From: Jeff Layton <jlayton@kernel.org>
+
+commit f9a348e0de19226fc3c7e81de7677d3fa2c4b2d8 upstream.
+
+Clients will typically precede a DELEGRETURN for a delegation with
+delegated timestamp with a SETATTR to set the timestamps on the server
+to match what the client has.
+
+knfsd implements this by using the nfsd_setattr() infrastructure, which
+will set ATTR_CTIME on any update that goes to notify_change(). This is
+problematic as it means that the client will get a spurious ctime
+update when updating the atime.
+
+POSIX unfortunately doesn't phrase it succinctly, but updating the atime
+due to reads should not update the ctime. In this case, the client is
+sending a SETATTR to update the atime on the server to match its latest
+value. The ctime should not be advanced in this case as that would
+incorrectly indicate a change to the inode.
+
+Fix this by not implicitly setting ATTR_CTIME when ATTR_DELEG is set in
+__nfsd_setattr(). The decoder for FATTR4_WORD2_TIME_DELEG_MODIFY already
+sets ATTR_CTIME, so this is sufficient to make it skip setting the ctime
+on atime-only updates.
+
+Fixes: 7e13f4f8d27d ("nfsd: handle delegated timestamps in SETATTR")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/vfs.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -470,7 +470,15 @@ static int __nfsd_setattr(struct dentry
+       if (!iap->ia_valid)
+               return 0;
+-      iap->ia_valid |= ATTR_CTIME;
++      /*
++       * If ATTR_DELEG is set, then this is an update from a client that
++       * holds a delegation. If this is an update for only the atime, the
++       * ctime should not be changed. If the update contains the mtime
++       * too, then ATTR_CTIME should already be set.
++       */
++      if (!(iap->ia_valid & ATTR_DELEG))
++              iap->ia_valid |= ATTR_CTIME;
++
+       return notify_change(&nop_mnt_idmap, dentry, iap, NULL);
+ }
diff --git a/queue-6.16/pwm-rockchip-round-period-duty-down-on-apply-up-on-g.patch b/queue-6.16/pwm-rockchip-round-period-duty-down-on-apply-up-on-g.patch
deleted file mode 100644 (file)
index df54418..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-From 51144efa3159cd95ab37e786c982822a060d7d1a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 16 Jun 2025 17:14:17 +0200
-Subject: pwm: rockchip: Round period/duty down on apply, up on get
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
-
-[ Upstream commit 0b4d1abe5ca568c5b7f667345ec2b5ad0fb2e54b ]
-
-With CONFIG_PWM_DEBUG=y, the rockchip PWM driver produces warnings like
-this:
-
-  rockchip-pwm fd8b0010.pwm: .apply is supposed to round down
-  duty_cycle (requested: 23529/50000, applied: 23542/50000)
-
-This is because the driver chooses ROUND_CLOSEST for purported
-idempotency reasons. However, it's possible to keep idempotency while
-always rounding down in .apply().
-
-Do this by making .get_state() always round up, and making .apply()
-always round down. This is done with u64 maths, and setting both period
-and duty to U32_MAX (the biggest the hardware can support) if they would
-exceed their 32 bits confines.
-
-Fixes: 12f9ce4a5198 ("pwm: rockchip: Fix period and duty cycle approximation")
-Fixes: 1ebb74cf3537 ("pwm: rockchip: Add support for hardware readout")
-Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
-Link: https://lore.kernel.org/r/20250616-rockchip-pwm-rounding-fix-v2-1-a9c65acad7b6@collabora.com
-Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/pwm/pwm-rockchip.c | 33 ++++++++++++++++++++-------------
- 1 file changed, 20 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
-index c5f50e5eaf41..67b85bdb491b 100644
---- a/drivers/pwm/pwm-rockchip.c
-+++ b/drivers/pwm/pwm-rockchip.c
-@@ -8,6 +8,8 @@
- #include <linux/clk.h>
- #include <linux/io.h>
-+#include <linux/limits.h>
-+#include <linux/math64.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/platform_device.h>
-@@ -61,6 +63,7 @@ static int rockchip_pwm_get_state(struct pwm_chip *chip,
-                                 struct pwm_state *state)
- {
-       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
-+      u64 prescaled_ns = (u64)pc->data->prescaler * NSEC_PER_SEC;
-       u32 enable_conf = pc->data->enable_conf;
-       unsigned long clk_rate;
-       u64 tmp;
-@@ -78,12 +81,12 @@ static int rockchip_pwm_get_state(struct pwm_chip *chip,
-       clk_rate = clk_get_rate(pc->clk);
-       tmp = readl_relaxed(pc->base + pc->data->regs.period);
--      tmp *= pc->data->prescaler * NSEC_PER_SEC;
--      state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
-+      tmp *= prescaled_ns;
-+      state->period = DIV_U64_ROUND_UP(tmp, clk_rate);
-       tmp = readl_relaxed(pc->base + pc->data->regs.duty);
--      tmp *= pc->data->prescaler * NSEC_PER_SEC;
--      state->duty_cycle =  DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
-+      tmp *= prescaled_ns;
-+      state->duty_cycle =  DIV_U64_ROUND_UP(tmp, clk_rate);
-       val = readl_relaxed(pc->base + pc->data->regs.ctrl);
-       state->enabled = (val & enable_conf) == enable_conf;
-@@ -103,8 +106,9 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                              const struct pwm_state *state)
- {
-       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
--      unsigned long period, duty;
--      u64 clk_rate, div;
-+      u64 prescaled_ns = (u64)pc->data->prescaler * NSEC_PER_SEC;
-+      u64 clk_rate, tmp;
-+      u32 period_ticks, duty_ticks;
-       u32 ctrl;
-       clk_rate = clk_get_rate(pc->clk);
-@@ -114,12 +118,15 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-        * bits, every possible input period can be obtained using the
-        * default prescaler value for all practical clock rate values.
-        */
--      div = clk_rate * state->period;
--      period = DIV_ROUND_CLOSEST_ULL(div,
--                                     pc->data->prescaler * NSEC_PER_SEC);
-+      tmp = mul_u64_u64_div_u64(clk_rate, state->period, prescaled_ns);
-+      if (tmp > U32_MAX)
-+              tmp = U32_MAX;
-+      period_ticks = tmp;
--      div = clk_rate * state->duty_cycle;
--      duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC);
-+      tmp = mul_u64_u64_div_u64(clk_rate, state->duty_cycle, prescaled_ns);
-+      if (tmp > U32_MAX)
-+              tmp = U32_MAX;
-+      duty_ticks = tmp;
-       /*
-        * Lock the period and duty of previous configuration, then
-@@ -131,8 +138,8 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-               writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl);
-       }
--      writel(period, pc->base + pc->data->regs.period);
--      writel(duty, pc->base + pc->data->regs.duty);
-+      writel(period_ticks, pc->base + pc->data->regs.period);
-+      writel(duty_ticks, pc->base + pc->data->regs.duty);
-       if (pc->data->supports_polarity) {
-               ctrl &= ~PWM_POLARITY_MASK;
--- 
-2.39.5
-
diff --git a/queue-6.16/sched-do-not-call-__put_task_struct-on-rt-if-pi_bloc.patch b/queue-6.16/sched-do-not-call-__put_task_struct-on-rt-if-pi_bloc.patch
deleted file mode 100644 (file)
index 5925702..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-From 7bed29f5ad955444283dca82476dd92c59923f73 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 7 Jul 2025 11:03:59 -0300
-Subject: sched: Do not call __put_task_struct() on rt if pi_blocked_on is set
-
-From: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
-
-[ Upstream commit 8671bad873ebeb082afcf7b4501395c374da6023 ]
-
-With PREEMPT_RT enabled, some of the calls to put_task_struct() coming
-from rt_mutex_adjust_prio_chain() could happen in preemptible context and
-with a mutex enqueued. That could lead to this sequence:
-
-        rt_mutex_adjust_prio_chain()
-          put_task_struct()
-            __put_task_struct()
-              sched_ext_free()
-                spin_lock_irqsave()
-                  rtlock_lock() --->  TRIGGERS
-                                      lockdep_assert(!current->pi_blocked_on);
-
-This is not a SCHED_EXT bug. The first cleanup function called by
-__put_task_struct() is sched_ext_free() and it happens to take a
-(RT) spin_lock, which in the scenario described above, would trigger
-the lockdep assertion of "!current->pi_blocked_on".
-
-Crystal Wood was able to identify the problem as __put_task_struct()
-being called during rt_mutex_adjust_prio_chain(), in the context of
-a process with a mutex enqueued.
-
-Instead of adding more complex conditions to decide when to directly
-call __put_task_struct() and when to defer the call, unconditionally
-resort to the deferred call on PREEMPT_RT to simplify the code.
-
-Fixes: 893cdaaa3977 ("sched: avoid false lockdep splat in put_task_struct()")
-Suggested-by: Crystal Wood <crwood@redhat.com>
-Signed-off-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
-Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-Reviewed-by: Wander Lairson Costa <wander@redhat.com>
-Reviewed-by: Valentin Schneider <vschneid@redhat.com>
-Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/aGvTz5VaPFyj0pBV@uudg.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/linux/sched/task.h | 27 ++++++++++-----------------
- 1 file changed, 10 insertions(+), 17 deletions(-)
-
-diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
-index ca1db4b92c32..58ce71715268 100644
---- a/include/linux/sched/task.h
-+++ b/include/linux/sched/task.h
-@@ -135,24 +135,17 @@ static inline void put_task_struct(struct task_struct *t)
-               return;
-       /*
--       * In !RT, it is always safe to call __put_task_struct().
--       * Under RT, we can only call it in preemptible context.
--       */
--      if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible()) {
--              static DEFINE_WAIT_OVERRIDE_MAP(put_task_map, LD_WAIT_SLEEP);
--
--              lock_map_acquire_try(&put_task_map);
--              __put_task_struct(t);
--              lock_map_release(&put_task_map);
--              return;
--      }
--
--      /*
--       * under PREEMPT_RT, we can't call put_task_struct
-+       * Under PREEMPT_RT, we can't call __put_task_struct
-        * in atomic context because it will indirectly
--       * acquire sleeping locks.
-+       * acquire sleeping locks. The same is true if the
-+       * current process has a mutex enqueued (blocked on
-+       * a PI chain).
-+       *
-+       * In !RT, it is always safe to call __put_task_struct().
-+       * Though, in order to simplify the code, resort to the
-+       * deferred call too.
-        *
--       * call_rcu() will schedule delayed_put_task_struct_rcu()
-+       * call_rcu() will schedule __put_task_struct_rcu_cb()
-        * to be called in process context.
-        *
-        * __put_task_struct() is called when
-@@ -165,7 +158,7 @@ static inline void put_task_struct(struct task_struct *t)
-        *
-        * delayed_free_task() also uses ->rcu, but it is only called
-        * when it fails to fork a process. Therefore, there is no
--       * way it can conflict with put_task_struct().
-+       * way it can conflict with __put_task_struct().
-        */
-       call_rcu(&t->rcu, __put_task_struct_rcu_cb);
- }
--- 
-2.39.5
-
index 150b91d5d921cb9cedc825a719297456c1fc4771..18748c92a68c0091d719302d5ff563fc6d4e7578 100644 (file)
@@ -87,7 +87,6 @@ revert-vmci-prevent-the-dispatching-of-uninitialized.patch
 powercap-dtpm_cpu-fix-null-pointer-dereference-in-ge.patch
 arm64-dts-ti-k3-am62p-verdin-add-sd_1-cd-pull-up.patch
 selftests-nolibc-correctly-report-errors-from-printf.patch
-pwm-rockchip-round-period-duty-down-on-apply-up-on-g.patch
 usb-early-xhci-dbc-fix-early_ioremap-leak.patch
 tools-nolibc-avoid-false-positive-wmaybe-uninitializ.patch
 arm-dts-ti-omap-fixup-pinheader-typo.patch
@@ -219,7 +218,6 @@ iommu-vt-d-do-not-wipe-out-the-page-table-nid-when-d.patch
 iommu-vt-d-fix-missing-pasid-in-dev-tlb-flush-with-c.patch
 iommu-arm-smmu-disable-prr-on-sm8250.patch
 xen-gntdev-remove-struct-gntdev_copy_batch-from-stac.patch
-sched-do-not-call-__put_task_struct-on-rt-if-pi_bloc.patch
 tcp-call-tcp_measure_rcv_mss-for-ooo-packets.patch
 wifi-rtl8xxxu-fix-rx-skb-size-for-aggregation-disabl.patch
 wifi-rtw88-fix-macid-assigned-to-tdls-station.patch
@@ -572,3 +570,6 @@ pptp-fix-pptp_xmit-error-path.patch
 smb-client-return-an-error-if-rdma_connect-does-not-.patch
 tools-power-turbostat-fix-bogus-syswatt-for-forked-p.patch
 tools-power-turbostat-fix-dmr-support.patch
+nfsd-don-t-set-the-ctime-on-delegated-atime-updates.patch
+nfsd-avoid-ref-leak-in-nfsd_open_local_fh.patch
+sunrpc-fix-handling-of-server-side-tls-alerts.patch
diff --git a/queue-6.16/sunrpc-fix-handling-of-server-side-tls-alerts.patch b/queue-6.16/sunrpc-fix-handling-of-server-side-tls-alerts.patch
new file mode 100644 (file)
index 0000000..99c5e05
--- /dev/null
@@ -0,0 +1,114 @@
+From bee47cb026e762841f3faece47b51f985e215edb Mon Sep 17 00:00:00 2001
+From: Olga Kornievskaia <okorniev@redhat.com>
+Date: Tue, 29 Jul 2025 12:40:20 -0400
+Subject: sunrpc: fix handling of server side tls alerts
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+commit bee47cb026e762841f3faece47b51f985e215edb upstream.
+
+Scott Mayhew discovered a security exploit in NFS over TLS in
+tls_alert_recv() due to its assumption it can read data from
+the msg iterator's kvec..
+
+kTLS implementation splits TLS non-data record payload between
+the control message buffer (which includes the type such as TLS
+aler or TLS cipher change) and the rest of the payload (say TLS
+alert's level/description) which goes into the msg payload buffer.
+
+This patch proposes to rework how control messages are setup and
+used by sock_recvmsg().
+
+If no control message structure is setup, kTLS layer will read and
+process TLS data record types. As soon as it encounters a TLS control
+message, it would return an error. At that point, NFS can setup a
+kvec backed msg buffer and read in the control message such as a
+TLS alert. Msg iterator can advance the kvec pointer as a part of
+the copy process thus we need to revert the iterator before calling
+into the tls_alert_recv.
+
+Reported-by: Scott Mayhew <smayhew@redhat.com>
+Fixes: 5e052dda121e ("SUNRPC: Recognize control messages in server-side TCP socket code")
+Suggested-by: Trond Myklebust <trondmy@hammerspace.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/svcsock.c |   43 +++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 35 insertions(+), 8 deletions(-)
+
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -257,20 +257,47 @@ svc_tcp_sock_process_cmsg(struct socket
+ }
+ static int
+-svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg)
++svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
+ {
+       union {
+               struct cmsghdr  cmsg;
+               u8              buf[CMSG_SPACE(sizeof(u8))];
+       } u;
+-      struct socket *sock = svsk->sk_sock;
++      u8 alert[2];
++      struct kvec alert_kvec = {
++              .iov_base = alert,
++              .iov_len = sizeof(alert),
++      };
++      struct msghdr msg = {
++              .msg_flags = *msg_flags,
++              .msg_control = &u,
++              .msg_controllen = sizeof(u),
++      };
++      int ret;
++
++      iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
++                    alert_kvec.iov_len);
++      ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT);
++      if (ret > 0 &&
++          tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
++              iov_iter_revert(&msg.msg_iter, ret);
++              ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
++      }
++      return ret;
++}
++
++static int
++svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
++{
+       int ret;
++      struct socket *sock = svsk->sk_sock;
+-      msg->msg_control = &u;
+-      msg->msg_controllen = sizeof(u);
+       ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
+-      if (unlikely(msg->msg_controllen != sizeof(u)))
+-              ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret);
++      if (msg->msg_flags & MSG_CTRUNC) {
++              msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
++              if (ret == 0 || ret == -EIO)
++                      ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);
++      }
+       return ret;
+ }
+@@ -321,7 +348,7 @@ static ssize_t svc_tcp_read_msg(struct s
+               iov_iter_advance(&msg.msg_iter, seek);
+               buflen -= seek;
+       }
+-      len = svc_tcp_sock_recv_cmsg(svsk, &msg);
++      len = svc_tcp_sock_recvmsg(svsk, &msg);
+       if (len > 0)
+               svc_flush_bvec(bvec, len, seek);
+@@ -1018,7 +1045,7 @@ static ssize_t svc_tcp_read_marker(struc
+               iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
+               iov.iov_len  = want;
+               iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want);
+-              len = svc_tcp_sock_recv_cmsg(svsk, &msg);
++              len = svc_tcp_sock_recvmsg(svsk, &msg);
+               if (len < 0)
+                       return len;
+               svsk->sk_tcplen += len;