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/14388 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/R...
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/14388 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/R...
hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAFI CVE: CVE-2024-53173
--------------------------------
This reverts commit 5cd78a98a34d1f2051883e9f97531582925d6b95.
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: 5cd78a98a34d ("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 c5f8a3c0df7a..84a6a18335c5 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3606,7 +3606,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: done, 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 7db58faf0624b02b6c9f368b712f425c9ab76064.
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: 7db58faf0624 ("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 2dc59e79295d..8b41c0b8624e 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -521,7 +521,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 84a6a18335c5..2f9505f5bd1b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2518,8 +2518,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 6ed5b0cc4d1b..f03b956ef77f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1088,24 +1088,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/src-openeuler/kernel/issues/IBEAFI 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 f03b956ef77f..3504eb6edd1d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1096,14 +1096,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-v5.10.231 commit 5237a297ffd374a1c4157a53543b7a69d7bbbc03 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAFI 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 2f9505f5bd1b..8dc77a194c62 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2518,12 +2518,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;