diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-08-24 01:03:05 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:24:54 -0400 |
commit | 5dd3177ae5012c1e2ad7a9ffdbd0e0d0de2f60e4 (patch) | |
tree | 2a8730d6443f6d33e8879cfc323396f9a570b97b /fs/nfs/client.c | |
parent | 275a082fe9308e710324e26ccb5363c53d8fd45f (diff) |
NFSv4: Fix a use-after-free issue with the nfs server.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 12941a8a6d75..f1ff2aec2ca5 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -164,6 +164,26 @@ error_0: | |||
164 | return NULL; | 164 | return NULL; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void nfs4_shutdown_client(struct nfs_client *clp) | ||
168 | { | ||
169 | #ifdef CONFIG_NFS_V4 | ||
170 | if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) | ||
171 | nfs4_kill_renewd(clp); | ||
172 | while (!list_empty(&clp->cl_unused)) { | ||
173 | struct nfs4_state_owner *sp; | ||
174 | |||
175 | sp = list_entry(clp->cl_unused.next, | ||
176 | struct nfs4_state_owner, | ||
177 | so_list); | ||
178 | list_del(&sp->so_list); | ||
179 | kfree(sp); | ||
180 | } | ||
181 | BUG_ON(!list_empty(&clp->cl_state_owners)); | ||
182 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) | ||
183 | nfs_idmap_delete(clp); | ||
184 | #endif | ||
185 | } | ||
186 | |||
167 | /* | 187 | /* |
168 | * Destroy a shared client record | 188 | * Destroy a shared client record |
169 | */ | 189 | */ |
@@ -171,21 +191,7 @@ static void nfs_free_client(struct nfs_client *clp) | |||
171 | { | 191 | { |
172 | dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); | 192 | dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); |
173 | 193 | ||
174 | #ifdef CONFIG_NFS_V4 | 194 | nfs4_shutdown_client(clp); |
175 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) { | ||
176 | while (!list_empty(&clp->cl_unused)) { | ||
177 | struct nfs4_state_owner *sp; | ||
178 | |||
179 | sp = list_entry(clp->cl_unused.next, | ||
180 | struct nfs4_state_owner, | ||
181 | so_list); | ||
182 | list_del(&sp->so_list); | ||
183 | kfree(sp); | ||
184 | } | ||
185 | BUG_ON(!list_empty(&clp->cl_state_owners)); | ||
186 | nfs_idmap_delete(clp); | ||
187 | } | ||
188 | #endif | ||
189 | 195 | ||
190 | /* -EIO all pending I/O */ | 196 | /* -EIO all pending I/O */ |
191 | if (!IS_ERR(clp->cl_rpcclient)) | 197 | if (!IS_ERR(clp->cl_rpcclient)) |