Skip to content

Commit 85f7809

Browse files
chuckleveraloktiwa
authored andcommitted
NFSD: Limit the number of concurrent async COPY operations
[ Upstream commit aadc3bb ] 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: [email protected] Reviewed-by: Jeff Layton <[email protected]> Link: https://nvd.nist.gov/vuln/detail/CVE-2024-49974 Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Orabug: 37206187 (cherry picked from commit 9e52ff544e0bfa09ee339fd7b0937ee3c080c24e) Signed-off-by: Samasth Norway Ananda <[email protected]> Reviewed-by: Calum Mackay <[email protected]> Conflict: fs/nfsd/nfs4proc.c - due to codebase change in UEK6 code Signed-off-by: Alok Tiwari <[email protected]>
1 parent c784af6 commit 85f7809

File tree

4 files changed

+12
-2
lines changed

4 files changed

+12
-2
lines changed

fs/nfsd/netns.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct nfsd_net {
128128
u32 s2s_cp_cl_id;
129129
struct idr s2s_cp_stateids;
130130
spinlock_t s2s_cp_lock;
131+
atomic_t pending_async_copies;
131132

132133
/*
133134
* Version information

fs/nfsd/nfs4proc.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,7 @@ void nfs4_put_copy(struct nfsd4_copy *copy)
11031103
{
11041104
if (!refcount_dec_and_test(&copy->refcount))
11051105
return;
1106+
atomic_dec(&copy->cp_nn->pending_async_copies);
11061107
kfree(copy);
11071108
}
11081109

@@ -1531,10 +1532,16 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
15311532
if (!copy->cp_synchronous) {
15321533
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
15331534

1534-
status = nfserrno(-ENOMEM);
15351535
async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
15361536
if (!async_copy)
15371537
goto out_err;
1538+
async_copy->cp_nn = nn;
1539+
/* Arbitrary cap on number of pending async copy operations */
1540+
if (atomic_inc_return(&nn->pending_async_copies) >
1541+
(int)rqstp->rq_pool->sp_nrthreads) {
1542+
atomic_dec(&nn->pending_async_copies);
1543+
goto out_err;
1544+
}
15381545
if (!nfs4_init_copy_state(nn, copy))
15391546
goto out_err;
15401547
refcount_set(&async_copy->refcount, 1);
@@ -1561,7 +1568,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
15611568
out_err:
15621569
if (async_copy)
15631570
cleanup_async_copy(async_copy);
1564-
status = nfserrno(-ENOMEM);
1571+
status = nfserr_jukebox;
15651572
if (!copy->cp_intra)
15661573
nfsd4_interssc_disconnect(copy->ss_mnt);
15671574
goto out;

fs/nfsd/nfs4state.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7907,6 +7907,7 @@ static int nfs4_state_create_net(struct net *net)
79077907
spin_lock_init(&nn->client_lock);
79087908
spin_lock_init(&nn->s2s_cp_lock);
79097909
idr_init(&nn->s2s_cp_stateids);
7910+
atomic_set(&nn->pending_async_copies, 0);
79107911

79117912
spin_lock_init(&nn->blocked_locks_lock);
79127913
INIT_LIST_HEAD(&nn->blocked_locks_lru);

fs/nfsd/xdr4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ struct nfsd4_copy {
553553
struct vfsmount *ss_mnt;
554554
struct nfs_fh c_fh;
555555
nfs4_stateid stateid;
556+
struct nfsd_net *cp_nn;
556557
};
557558
extern bool inter_copy_offload_enable;
558559

0 commit comments

Comments
 (0)