Commit 5dd3177ae5012c1e2ad7a9ffdbd0e0d0de2f60e4
1 parent
275a082fe9
Exists in
master
and in
7 other branches
NFSv4: Fix a use-after-free issue with the nfs server.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 4 changed files with 28 additions and 18 deletions Side-by-side Diff
fs/nfs/client.c
... | ... | @@ -164,6 +164,26 @@ |
164 | 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 | 188 | * Destroy a shared client record |
169 | 189 | */ |
... | ... | @@ -171,21 +191,7 @@ |
171 | 191 | { |
172 | 192 | dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); |
173 | 193 | |
174 | -#ifdef CONFIG_NFS_V4 | |
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 | |
194 | + nfs4_shutdown_client(clp); | |
189 | 195 | |
190 | 196 | /* -EIO all pending I/O */ |
191 | 197 | if (!IS_ERR(clp->cl_rpcclient)) |
fs/nfs/nfs4renewd.c
fs/nfs/super.c
... | ... | @@ -883,13 +883,15 @@ |
883 | 883 | goto out_free; |
884 | 884 | } |
885 | 885 | |
886 | + if (s->s_fs_info != server) { | |
887 | + nfs_free_server(server); | |
888 | + server = NULL; | |
889 | + } | |
890 | + | |
886 | 891 | if (!s->s_root) { |
887 | 892 | /* initial superblock/root creation */ |
888 | 893 | s->s_flags = flags; |
889 | - | |
890 | 894 | nfs4_fill_super(s); |
891 | - } else { | |
892 | - nfs_free_server(server); | |
893 | 895 | } |
894 | 896 | |
895 | 897 | mntroot = nfs4_get_root(s, &mntfh); |
include/linux/nfs_fs_sb.h
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | #define NFS_CS_RPCIOD 0 /* - rpciod started */ |
20 | 20 | #define NFS_CS_CALLBACK 1 /* - callback started */ |
21 | 21 | #define NFS_CS_IDMAP 2 /* - idmap started */ |
22 | +#define NFS_CS_RENEWD 3 /* - renewd started */ | |
22 | 23 | struct sockaddr_in cl_addr; /* server identifier */ |
23 | 24 | char * cl_hostname; /* hostname of server */ |
24 | 25 | struct list_head cl_share_link; /* link in global client list */ |