Li Lingfeng (2): Revert "nfs: fix rpc_task use-after-free when open and close different files concurrently" Revert "NFSv4: release seqid when open failed for nfs4.0"
Trond Myklebust (2): NFSv4.0: Fix the wake up of the next waiter in nfs_release_seqid() NFSv4.0: Fix a use-after-free problem in the asynchronous open()
fs/nfs/nfs4_fs.h | 1 - fs/nfs/nfs4proc.c | 12 ++++++------ fs/nfs/nfs4state.c | 28 ++++------------------------ 3 files changed, 10 insertions(+), 31 deletions(-)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/14389 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/J...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/14389 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/J...
hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAFI CVE: CVE-2024-53173
--------------------------------
This reverts commit 4f97f8597cf1cac4dd2a5834197b9a7b221dcaff.
The issue is resolved by replace nfs_release_seqid with nfs_release_seqid_inorder. The later patch will change nfs_release_seqid directly and nfs_release_seqid_inorder will be not necessary any more.
Fixes: 4f97f8597cf1 ("nfs: fix rpc_task use-after-free when open and close different files concurrently") Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8e57c396fd37..944edd332309 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3612,7 +3612,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) res_stateid, calldata->arg.fmode); out_release: task->tk_status = 0; - nfs_release_seqid_inorder(calldata->arg.seqid); + nfs_release_seqid(calldata->arg.seqid); nfs_refresh_inode(calldata->inode, &calldata->fattr); dprintk("%s: ret = %d\n", __func__, task->tk_status); return;
hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAFI CVE: CVE-2024-53173
--------------------------------
This reverts commit 8a6f6a9db172b695e45be869e515ac87557dbfb7.
The issue is resolved by replace nfs_release_seqid with nfs_release_seqid_inorder. The later patch will change nfs_release_seqid directly and nfs_release_seqid_inorder will be not necessary any more.
Fixes: 8a6f6a9db172 ("NFSv4: release seqid when open failed for nfs4.0") Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- fs/nfs/nfs4_fs.h | 1 - fs/nfs/nfs4proc.c | 2 -- fs/nfs/nfs4state.c | 18 ------------------ 3 files changed, 21 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 4187ce22c623..47c5c1f86d66 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -524,7 +524,6 @@ extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_ extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); -extern void nfs_release_seqid_inorder(struct nfs_seqid *seqid); extern void nfs_release_seqid(struct nfs_seqid *seqid); extern void nfs_free_seqid(struct nfs_seqid *seqid); extern int nfs4_setup_sequence(struct nfs_client *client, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 944edd332309..299ea2b86df6 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2528,8 +2528,6 @@ static void nfs4_open_release(void *calldata) struct nfs4_opendata *data = calldata; struct nfs4_state *state = NULL;
- if (data->rpc_status != 0 || !data->rpc_done) - nfs_release_seqid_inorder(data->o_arg.seqid); /* If this request hasn't been cancelled, do nothing */ if (!data->cancelled) goto out_free; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 099d3d8de779..794bb4aa588d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1087,24 +1087,6 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_m return new; }
-void nfs_release_seqid_inorder(struct nfs_seqid *seqid) -{ - struct nfs_seqid_counter *sequence; - - if (seqid == NULL || list_empty(&seqid->list)) - return; - sequence = seqid->sequence; - spin_lock(&sequence->lock); - if (!list_is_last(&seqid->list, &sequence->list)) { - struct nfs_seqid *next; - - next = list_next_entry(seqid, list); - rpc_wake_up_queued_task(&sequence->wait, next->task); - } - list_del_init(&seqid->list); - spin_unlock(&sequence->lock); -} - void nfs_release_seqid(struct nfs_seqid *seqid) { struct nfs_seqid_counter *sequence;
From: Trond Myklebust trond.myklebust@hammerspace.com
mainline inclusion from mainline-v6.13-rc1 commit c968fd23c68e9929ab6cad4faffc8ea603e98e5d category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBBR8I CVE: CVE-2024-53173
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
There is no need to wake up another waiter on the seqid list unless the seqid being removed is at the head of the list, and so is relinquishing control of the sequence counter to the next entry.
Reviewed-by: Yang Erkun yangerkun@huawei.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- fs/nfs/nfs4state.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 794bb4aa588d..8515d3db7166 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1095,14 +1095,12 @@ void nfs_release_seqid(struct nfs_seqid *seqid) return; sequence = seqid->sequence; spin_lock(&sequence->lock); - list_del_init(&seqid->list); - if (!list_empty(&sequence->list)) { - struct nfs_seqid *next; - - next = list_first_entry(&sequence->list, - struct nfs_seqid, list); + if (list_is_first(&seqid->list, &sequence->list) && + !list_is_singular(&sequence->list)) { + struct nfs_seqid *next = list_next_entry(seqid, list); rpc_wake_up_queued_task(&sequence->wait, next->task); } + list_del_init(&seqid->list); spin_unlock(&sequence->lock); }
From: Trond Myklebust trond.myklebust@hammerspace.com
stable inclusion from stable-v6.6.64 commit 229a30ed42bb87bcb044c5523fabd9e4f0e75648 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBBR8I CVE: CVE-2024-53173
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 2fdb05dc0931250574f0cb0ebeb5ed8e20f4a889 ]
Yang Erkun reports that when two threads are opening files at the same time, and are forced to abort before a reply is seen, then the call to nfs_release_seqid() in nfs4_opendata_free() can result in a use-after-free of the pointer to the defunct rpc task of the other thread. The fix is to ensure that if the RPC call is aborted before the call to nfs_wait_on_sequence() is complete, then we must call nfs_release_seqid() in nfs4_open_release() before the rpc_task is freed.
Reported-by: Yang Erkun yangerkun@huawei.com Fixes: 24ac23ab88df ("NFSv4: Convert open() into an asynchronous RPC call") Reviewed-by: Yang Erkun yangerkun@huawei.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- fs/nfs/nfs4proc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 299ea2b86df6..4b12e45f5753 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2528,12 +2528,14 @@ static void nfs4_open_release(void *calldata) struct nfs4_opendata *data = calldata; struct nfs4_state *state = NULL;
+ /* In case of error, no cleanup! */ + if (data->rpc_status != 0 || !data->rpc_done) { + nfs_release_seqid(data->o_arg.seqid); + goto out_free; + } /* If this request hasn't been cancelled, do nothing */ if (!data->cancelled) goto out_free; - /* In case of error, no cleanup! */ - if (data->rpc_status != 0 || !data->rpc_done) - goto out_free; /* In case we need an open_confirm, no cleanup! */ if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) goto out_free;