From: cel@kernel.org
To: <stable@vger.kernel.org>
Cc: <linux-nfs@vger.kernel.org>, Jeff Layton <jlayton@kernel.org>,
Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH 5.15 3/5] NFSD: Limit the number of concurrent async COPY operations
Date: Mon, 18 Nov 2024 16:23:41 -0500 [thread overview]
Message-ID: <20241118212343.3935-4-cel@kernel.org> (raw)
In-Reply-To: <20241118212343.3935-1-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>
---
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(-)
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 548422b24a7d..41c750f34473 100644
--- 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
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 08d90e0e8fae..54f43501fed9 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1244,6 +1244,7 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
{
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, struct nfsd4_compound_state *cstate,
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 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}
if (async_copy)
cleanup_async_copy(async_copy);
- status = nfserrno(-ENOMEM);
+ status = nfserr_jukebox;
goto out;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5ab3045c649f..a7016f738647 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -8079,6 +8079,7 @@ static int nfs4_state_create_net(struct net *net)
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);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 510978e602da..9bd1ade6ba54 100644
--- 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)
--
2.47.0
WARNING: multiple messages have this Message-ID (diff)
From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: cel@kernel.org, Sasha Levin <sashal@kernel.org>
Subject: Re: [PATCH 5.15 3/5] NFSD: Limit the number of concurrent async COPY operations
Date: Tue, 19 Nov 2024 07:31:04 -0500 [thread overview]
Message-ID: <20241118212343.3935-4-cel@kernel.org> (raw)
Message-ID: <20241119123104.dVlrw0YguAAbqbGdD-WLQO_oCLHC9ntv96acpKycv_A@z> (raw)
In-Reply-To: <20241118212343.3935-4-cel@kernel.org>
[ Sasha's backport helper bot ]
Hi,
The upstream commit SHA1 provided is correct: aadc3bbea163b6caaaebfdd2b6c4667fbc726752
WARNING: Author mismatch between patch and upstream commit:
Backport author: cel@kernel.org
Commit author: Chuck Lever <chuck.lever@oracle.com>
Commit in newer trees:
|-----------------|----------------------------------------------|
| 6.11.y | Present (different SHA1: 6a488ad7745b) |
| 6.6.y | Not found |
| 6.1.y | Not found |
| 5.15.y | Not found |
|-----------------|----------------------------------------------|
Note: The patch differs from the upstream commit:
---
--- - 2024-11-19 00:43:12.383139987 -0500
+++ /tmp/tmp.V5JZzwiFRS 2024-11-19 00:43:12.377009616 -0500
@@ -1,3 +1,5 @@
+[ 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
@@ -17,6 +19,7 @@
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>
---
fs/nfsd/netns.h | 1 +
@@ -26,10 +29,10 @@
4 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
-index 238fc4e56e539..37b8bfdcfeea8 100644
+index 548422b24a7d..41c750f34473 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
-@@ -148,6 +148,7 @@ struct nfsd_net {
+@@ -152,6 +152,7 @@ struct nfsd_net {
u32 s2s_cp_cl_id;
struct idr s2s_cp_stateids;
spinlock_t s2s_cp_lock;
@@ -38,10 +41,10 @@
/*
* Version information
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
-index 231c6035602f6..9655acb407b72 100644
+index 08d90e0e8fae..54f43501fed9 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
-@@ -1280,6 +1280,7 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
+@@ -1244,6 +1244,7 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
{
if (!refcount_dec_and_test(©->refcount))
return;
@@ -49,7 +52,7 @@
kfree(copy->cp_src);
kfree(copy);
}
-@@ -1835,10 +1836,16 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+@@ -1782,10 +1783,16 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
memcpy(©->fh, &cstate->current_fh.fh_handle,
sizeof(struct knfsd_fh));
if (nfsd4_copy_is_async(copy)) {
@@ -67,7 +70,7 @@
INIT_LIST_HEAD(&async_copy->copies);
refcount_set(&async_copy->refcount, 1);
async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
-@@ -1878,7 +1885,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+@@ -1824,7 +1831,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}
if (async_copy)
cleanup_async_copy(async_copy);
@@ -77,10 +80,10 @@
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
-index 7ade551bc0221..a49aa75bc0b79 100644
+index 5ab3045c649f..a7016f738647 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
-@@ -8554,6 +8554,7 @@ static int nfs4_state_create_net(struct net *net)
+@@ -8079,6 +8079,7 @@ static int nfs4_state_create_net(struct net *net)
spin_lock_init(&nn->client_lock);
spin_lock_init(&nn->s2s_cp_lock);
idr_init(&nn->s2s_cp_stateids);
@@ -89,10 +92,10 @@
spin_lock_init(&nn->blocked_locks_lock);
INIT_LIST_HEAD(&nn->blocked_locks_lru);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
-index fbdd42cde1fa5..2a21a7662e030 100644
+index 510978e602da..9bd1ade6ba54 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
-@@ -713,6 +713,7 @@ struct nfsd4_copy {
+@@ -574,6 +574,7 @@ struct nfsd4_copy {
struct nfsd4_ssc_umount_item *ss_nsui;
struct nfs_fh c_fh;
nfs4_stateid stateid;
@@ -100,3 +103,6 @@
};
static inline void nfsd4_copy_set_sync(struct nfsd4_copy *copy, bool sync)
+--
+2.47.0
+
---
Results of testing on various branches:
| Branch | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-5.15.y | Success | Success |
next prev parent reply other threads:[~2024-11-18 21:23 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-18 21:23 [PATCH 5.15 0/5] Address CVE-2024-49974 cel
2024-11-18 21:23 ` [PATCH 5.15 1/5] NFSD: initialize copy->cp_clp early in nfsd4_copy for use by trace point cel
2024-11-19 12:31 ` Sasha Levin
2024-11-18 21:23 ` [PATCH 5.15 2/5] NFSD: Async COPY result needs to return a write verifier cel
2024-11-19 12:31 ` Sasha Levin
2024-11-18 21:23 ` cel [this message]
2024-11-19 12:31 ` [PATCH 5.15 3/5] NFSD: Limit the number of concurrent async COPY operations Sasha Levin
2024-11-18 21:23 ` [PATCH 5.15 4/5] NFSD: Initialize struct nfsd4_copy earlier cel
2024-11-19 12:30 ` Sasha Levin
2024-11-18 21:23 ` [PATCH 5.15 5/5] NFSD: Never decrement pending_async_copies on error cel
2024-11-19 12:30 ` Sasha Levin
-- strict thread matches above, loose matches on Subject: below --
2024-11-18 21:20 [PATCH 5.15 0/5] Address CVE-2024-49974 cel
2024-11-18 21:20 ` [PATCH 5.15 3/5] NFSD: Limit the number of concurrent async COPY operations cel
2024-11-19 12:30 ` Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241118212343.3935-4-cel@kernel.org \
--to=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).