]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.15/nfsd-fix-problems-with-cleanup-on-errors-in-nfsd4_co.patch
Fixes for 5.15
[thirdparty/kernel/stable-queue.git] / queue-5.15 / nfsd-fix-problems-with-cleanup-on-errors-in-nfsd4_co.patch
1 From 135601fe8bddf569c37fc383e2e8fb38a5ddeceb Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Tue, 31 Jan 2023 11:12:29 -0800
4 Subject: NFSD: fix problems with cleanup on errors in nfsd4_copy
5
6 From: Dai Ngo <dai.ngo@oracle.com>
7
8 [ Upstream commit 81e722978ad21072470b73d8f6a50ad62c7d5b7d ]
9
10 When nfsd4_copy fails to allocate memory for async_copy->cp_src, or
11 nfs4_init_copy_state fails, it calls cleanup_async_copy to do the
12 cleanup for the async_copy which causes page fault since async_copy
13 is not yet initialized.
14
15 This patche rearranges the order of initializing the fields in
16 async_copy and adds checks in cleanup_async_copy to skip un-initialized
17 fields.
18
19 Fixes: ce0887ac96d3 ("NFSD add nfs4 inter ssc to nfsd4_copy")
20 Fixes: 87689df69491 ("NFSD: Shrink size of struct nfsd4_copy")
21 Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
22 Reviewed-by: Jeff Layton <jlayton@kernel.org>
23 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
24 ---
25 fs/nfsd/nfs4proc.c | 12 ++++++++----
26 fs/nfsd/nfs4state.c | 5 +++--
27 2 files changed, 11 insertions(+), 6 deletions(-)
28
29 diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
30 index c95e7ec5fb530..ba53cd89ec62c 100644
31 --- a/fs/nfsd/nfs4proc.c
32 +++ b/fs/nfsd/nfs4proc.c
33 @@ -1687,9 +1687,12 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)
34 {
35 nfs4_free_copy_state(copy);
36 release_copy_files(copy);
37 - spin_lock(&copy->cp_clp->async_lock);
38 - list_del(&copy->copies);
39 - spin_unlock(&copy->cp_clp->async_lock);
40 + if (copy->cp_clp) {
41 + spin_lock(&copy->cp_clp->async_lock);
42 + if (!list_empty(&copy->copies))
43 + list_del_init(&copy->copies);
44 + spin_unlock(&copy->cp_clp->async_lock);
45 + }
46 nfs4_put_copy(copy);
47 }
48
49 @@ -1786,12 +1789,13 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
50 async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
51 if (!async_copy)
52 goto out_err;
53 + INIT_LIST_HEAD(&async_copy->copies);
54 + refcount_set(&async_copy->refcount, 1);
55 async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
56 if (!async_copy->cp_src)
57 goto out_err;
58 if (!nfs4_init_copy_state(nn, copy))
59 goto out_err;
60 - refcount_set(&async_copy->refcount, 1);
61 memcpy(&copy->cp_res.cb_stateid, &copy->cp_stateid.cs_stid,
62 sizeof(copy->cp_res.cb_stateid));
63 dup_copy_fields(copy, async_copy);
64 diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
65 index 773971a75b62d..fab5805b3ca74 100644
66 --- a/fs/nfsd/nfs4state.c
67 +++ b/fs/nfsd/nfs4state.c
68 @@ -990,7 +990,6 @@ static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid,
69
70 stid->cs_stid.si_opaque.so_clid.cl_boot = (u32)nn->boot_time;
71 stid->cs_stid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id;
72 - stid->cs_type = cs_type;
73
74 idr_preload(GFP_KERNEL);
75 spin_lock(&nn->s2s_cp_lock);
76 @@ -1001,6 +1000,7 @@ static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid,
77 idr_preload_end();
78 if (new_id < 0)
79 return 0;
80 + stid->cs_type = cs_type;
81 return 1;
82 }
83
84 @@ -1034,7 +1034,8 @@ void nfs4_free_copy_state(struct nfsd4_copy *copy)
85 {
86 struct nfsd_net *nn;
87
88 - WARN_ON_ONCE(copy->cp_stateid.cs_type != NFS4_COPY_STID);
89 + if (copy->cp_stateid.cs_type != NFS4_COPY_STID)
90 + return;
91 nn = net_generic(copy->cp_clp->net, nfsd_net_id);
92 spin_lock(&nn->s2s_cp_lock);
93 idr_remove(&nn->s2s_cp_stateids,
94 --
95 2.43.0
96