--- /dev/null
+From stable+bounces-93884-greg=kroah.com@vger.kernel.org Tue Nov 19 01:47:50 2024
+From: cel@kernel.org
+Date: Mon, 18 Nov 2024 19:47:29 -0500
+Subject: NFSD: Async COPY result needs to return a write verifier
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>
+Message-ID: <20241119004732.4703-3-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9ed666eba4e0a2bb8ffaa3739d830b64d4f2aaad ]
+
+Currently, when NFSD handles an asynchronous COPY, it returns a
+zero write verifier, relying on the subsequent CB_OFFLOAD callback
+to pass the write verifier and a stable_how4 value to the client.
+
+However, if the CB_OFFLOAD never arrives at the client (for example,
+if a network partition occurs just as the server sends the
+CB_OFFLOAD operation), the client will never receive this verifier.
+Thus, if the client sends a follow-up COMMIT, there is no way for
+the client to assess the COMMIT result.
+
+The usual recovery for a missing CB_OFFLOAD is for the client to
+send an OFFLOAD_STATUS operation, but that operation does not carry
+a write verifier in its result. Neither does it carry a stable_how4
+value, so the client /must/ send a COMMIT in this case -- which will
+always fail because currently there's still no write verifier in the
+COPY result.
+
+Thus the server needs to return a normal write verifier in its COPY
+result even if the COPY operation is to be performed asynchronously.
+
+If the server recognizes the callback stateid in subsequent
+OFFLOAD_STATUS operations, then obviously it has not restarted, and
+the write verifier the client received in the COPY result is still
+valid and can be used to assess a COMMIT of the copied data, if one
+is needed.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+[ cel: adjusted to apply to origin/linux-5.10.y ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c | 23 ++++++++---------------
+ 1 file changed, 8 insertions(+), 15 deletions(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -718,15 +718,6 @@ nfsd4_access(struct svc_rqst *rqstp, str
+ &access->ac_supported);
+ }
+
+-static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
+-{
+- __be32 *verf = (__be32 *)verifier->data;
+-
+- BUILD_BUG_ON(2*sizeof(*verf) != sizeof(verifier->data));
+-
+- nfsd_copy_write_verifier(verf, net_generic(net, nfsd_net_id));
+-}
+-
+ static __be32
+ nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ union nfsd4_op_u *u)
+@@ -1594,7 +1585,6 @@ static void nfsd4_init_copy_res(struct n
+ test_bit(NFSD4_COPY_F_COMMITTED, ©->cp_flags) ?
+ NFS_FILE_SYNC : NFS_UNSTABLE;
+ nfsd4_copy_set_sync(copy, sync);
+- gen_boot_verifier(©->cp_res.wr_verifier, copy->cp_clp->net);
+ }
+
+ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy,
+@@ -1765,9 +1755,14 @@ static __be32
+ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ union nfsd4_op_u *u)
+ {
++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
++ struct nfsd4_copy *async_copy = NULL;
+ struct nfsd4_copy *copy = &u->copy;
++ struct nfsd42_write_res *result;
+ __be32 status;
+- struct nfsd4_copy *async_copy = NULL;
++
++ result = ©->cp_res;
++ nfsd_copy_write_verifier((__be32 *)&result->wr_verifier.data, nn);
+
+ copy->cp_clp = cstate->clp;
+ if (nfsd4_ssc_is_inter(copy)) {
+@@ -1787,8 +1782,6 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ memcpy(©->fh, &cstate->current_fh.fh_handle,
+ sizeof(struct knfsd_fh));
+ if (nfsd4_copy_is_async(copy)) {
+- struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+-
+ status = nfserrno(-ENOMEM);
+ async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
+ if (!async_copy)
+@@ -1800,8 +1793,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ goto out_err;
+ if (!nfs4_init_copy_state(nn, copy))
+ goto out_err;
+- memcpy(©->cp_res.cb_stateid, ©->cp_stateid.cs_stid,
+- sizeof(copy->cp_res.cb_stateid));
++ memcpy(&result->cb_stateid, ©->cp_stateid.cs_stid,
++ sizeof(result->cb_stateid));
+ dup_copy_fields(copy, async_copy);
+ async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
+ async_copy, "%s", "copy thread");
--- /dev/null
+From stable+bounces-93883-greg=kroah.com@vger.kernel.org Tue Nov 19 01:47:45 2024
+From: cel@kernel.org
+Date: Mon, 18 Nov 2024 19:47:28 -0500
+Subject: NFSD: initialize copy->cp_clp early in nfsd4_copy for use by trace point
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>, Dai Ngo <dai.ngo@oracle.com>, Chen Hanxiao <chenhx.fnst@fujitsu.com>
+Message-ID: <20241119004732.4703-2-cel@kernel.org>
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+[ Upstream commit 15d1975b7279693d6f09398e0e2e31aca2310275 ]
+
+Prepare for adding server copy trace points.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Tested-by: Chen Hanxiao <chenhx.fnst@fujitsu.com>
+Stable-dep-of: 9ed666eba4e0 ("NFSD: Async COPY result needs to return a write verifier")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1769,6 +1769,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ __be32 status;
+ struct nfsd4_copy *async_copy = NULL;
+
++ copy->cp_clp = cstate->clp;
+ if (nfsd4_ssc_is_inter(copy)) {
+ if (!inter_copy_offload_enable || nfsd4_copy_is_sync(copy)) {
+ status = nfserr_notsupp;
+@@ -1783,7 +1784,6 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ return status;
+ }
+
+- copy->cp_clp = cstate->clp;
+ memcpy(©->fh, &cstate->current_fh.fh_handle,
+ sizeof(struct knfsd_fh));
+ if (nfsd4_copy_is_async(copy)) {
--- /dev/null
+From stable+bounces-93886-greg=kroah.com@vger.kernel.org Tue Nov 19 01:47:58 2024
+From: cel@kernel.org
+Date: Mon, 18 Nov 2024 19:47:31 -0500
+Subject: NFSD: Initialize struct nfsd4_copy earlier
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Olga Kornievskaia <okorniev@redhat.com>
+Message-ID: <20241119004732.4703-5-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 63fab04cbd0f96191b6e5beedc3b643b01c15889 ]
+
+Ensure the refcount and async_copies fields are initialized early.
+cleanup_async_copy() will reference these fields if an error occurs
+in nfsd4_copy(). If they are not correctly initialized, at the very
+least, a refcount underflow occurs.
+
+Reported-by: Olga Kornievskaia <okorniev@redhat.com>
+Fixes: aadc3bbea163 ("NFSD: Limit the number of concurrent async COPY operations")
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Tested-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1787,14 +1787,14 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ if (!async_copy)
+ goto out_err;
+ async_copy->cp_nn = nn;
++ INIT_LIST_HEAD(&async_copy->copies);
++ refcount_set(&async_copy->refcount, 1);
+ /* Arbitrary cap on number of pending async copy operations */
+ if (atomic_inc_return(&nn->pending_async_copies) >
+ (int)rqstp->rq_pool->sp_nrthreads) {
+ atomic_dec(&nn->pending_async_copies);
+ goto out_err;
+ }
+- INIT_LIST_HEAD(&async_copy->copies);
+- refcount_set(&async_copy->refcount, 1);
+ async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
+ if (!async_copy->cp_src)
+ goto out_err;
--- /dev/null
+From stable+bounces-93885-greg=kroah.com@vger.kernel.org Tue Nov 19 01:47:54 2024
+From: cel@kernel.org
+Date: Mon, 18 Nov 2024 19:47:30 -0500
+Subject: NFSD: Limit the number of concurrent async COPY operations
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>
+Message-ID: <20241119004732.4703-4-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit aadc3bbea163b6caaaebfdd2b6c4667fbc726752 ]
+
+Nothing appears to limit the number of concurrent async COPY
+operations that clients can start. In addition, AFAICT each async
+COPY can copy an unlimited number of 4MB chunks, so can run for a
+long time. Thus IMO async COPY can become a DoS vector.
+
+Add a restriction mechanism that bounds the number of concurrent
+background COPY operations. Start simple and try to be fair -- this
+patch implements a per-namespace limit.
+
+An async COPY request that occurs while this limit is exceeded gets
+NFS4ERR_DELAY. The requesting client can choose to send the request
+again after a delay or fall back to a traditional read/write style
+copy.
+
+If there is need to make the mechanism more sophisticated, we can
+visit that in future patches.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Link: https://nvd.nist.gov/vuln/detail/CVE-2024-49974
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/netns.h | 1 +
+ fs/nfsd/nfs4proc.c | 11 +++++++++--
+ fs/nfsd/nfs4state.c | 1 +
+ fs/nfsd/xdr4.h | 1 +
+ 4 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -152,6 +152,7 @@ struct nfsd_net {
+ u32 s2s_cp_cl_id;
+ struct idr s2s_cp_stateids;
+ spinlock_t s2s_cp_lock;
++ atomic_t pending_async_copies;
+
+ /*
+ * Version information
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1244,6 +1244,7 @@ static void nfs4_put_copy(struct nfsd4_c
+ {
+ if (!refcount_dec_and_test(©->refcount))
+ return;
++ atomic_dec(©->cp_nn->pending_async_copies);
+ kfree(copy->cp_src);
+ kfree(copy);
+ }
+@@ -1782,10 +1783,16 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ memcpy(©->fh, &cstate->current_fh.fh_handle,
+ sizeof(struct knfsd_fh));
+ if (nfsd4_copy_is_async(copy)) {
+- status = nfserrno(-ENOMEM);
+ async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
+ if (!async_copy)
+ goto out_err;
++ async_copy->cp_nn = nn;
++ /* Arbitrary cap on number of pending async copy operations */
++ if (atomic_inc_return(&nn->pending_async_copies) >
++ (int)rqstp->rq_pool->sp_nrthreads) {
++ atomic_dec(&nn->pending_async_copies);
++ goto out_err;
++ }
+ INIT_LIST_HEAD(&async_copy->copies);
+ refcount_set(&async_copy->refcount, 1);
+ async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
+@@ -1824,7 +1831,7 @@ out_err:
+ }
+ if (async_copy)
+ cleanup_async_copy(async_copy);
+- status = nfserrno(-ENOMEM);
++ status = nfserr_jukebox;
+ goto out;
+ }
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -8088,6 +8088,7 @@ static int nfs4_state_create_net(struct
+ spin_lock_init(&nn->client_lock);
+ spin_lock_init(&nn->s2s_cp_lock);
+ idr_init(&nn->s2s_cp_stateids);
++ atomic_set(&nn->pending_async_copies, 0);
+
+ spin_lock_init(&nn->blocked_locks_lock);
+ INIT_LIST_HEAD(&nn->blocked_locks_lru);
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -574,6 +574,7 @@ struct nfsd4_copy {
+ struct nfsd4_ssc_umount_item *ss_nsui;
+ struct nfs_fh c_fh;
+ nfs4_stateid stateid;
++ struct nfsd_net *cp_nn;
+ };
+
+ static inline void nfsd4_copy_set_sync(struct nfsd4_copy *copy, bool sync)
--- /dev/null
+From stable+bounces-93887-greg=kroah.com@vger.kernel.org Tue Nov 19 01:47:59 2024
+From: cel@kernel.org
+Date: Mon, 18 Nov 2024 19:47:32 -0500
+Subject: NFSD: Never decrement pending_async_copies on error
+To: <stable@vger.kernel.org>
+Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Olga Kornievskaia <okorniev@redhat.com>
+Message-ID: <20241119004732.4703-6-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 8286f8b622990194207df9ab852e0f87c60d35e9 ]
+
+The error flow in nfsd4_copy() calls cleanup_async_copy(), which
+already decrements nn->pending_async_copies.
+
+Reported-by: Olga Kornievskaia <okorniev@redhat.com>
+Fixes: aadc3bbea163 ("NFSD: Limit the number of concurrent async COPY operations")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1791,10 +1791,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+ refcount_set(&async_copy->refcount, 1);
+ /* Arbitrary cap on number of pending async copy operations */
+ if (atomic_inc_return(&nn->pending_async_copies) >
+- (int)rqstp->rq_pool->sp_nrthreads) {
+- atomic_dec(&nn->pending_async_copies);
++ (int)rqstp->rq_pool->sp_nrthreads)
+ goto out_err;
+- }
+ async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
+ if (!async_copy->cp_src)
+ goto out_err;
drm-bridge-tc358768-fix-dsi-command-tx.patch
mmc-core-fix-return-value-check-in-devm_mmc_alloc_host.patch
media-dvbdev-fix-the-logic-when-dvb_dynamic_minors-is-not-set.patch
+nfsd-initialize-copy-cp_clp-early-in-nfsd4_copy-for-use-by-trace-point.patch
+nfsd-async-copy-result-needs-to-return-a-write-verifier.patch
+nfsd-limit-the-number-of-concurrent-async-copy-operations.patch
+nfsd-initialize-struct-nfsd4_copy-earlier.patch
+nfsd-never-decrement-pending_async_copies-on-error.patch