aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-08-24 01:03:05 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:24:54 -0400
commit5dd3177ae5012c1e2ad7a9ffdbd0e0d0de2f60e4 (patch)
tree2a8730d6443f6d33e8879cfc323396f9a570b97b
parent275a082fe9308e710324e26ccb5363c53d8fd45f (diff)
NFSv4: Fix a use-after-free issue with the nfs server.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c36
-rw-r--r--fs/nfs/nfs4renewd.c1
-rw-r--r--fs/nfs/super.c8
-rw-r--r--include/linux/nfs_fs_sb.h1
4 files changed, 28 insertions, 18 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
167static 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))
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index f2c893690ac4..7b6df1852e75 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -121,6 +121,7 @@ nfs4_schedule_state_renewal(struct nfs_client *clp)
121 __FUNCTION__, (timeout + HZ - 1) / HZ); 121 __FUNCTION__, (timeout + HZ - 1) / HZ);
122 cancel_delayed_work(&clp->cl_renewd); 122 cancel_delayed_work(&clp->cl_renewd);
123 schedule_delayed_work(&clp->cl_renewd, timeout); 123 schedule_delayed_work(&clp->cl_renewd, timeout);
124 set_bit(NFS_CS_RENEWD, &clp->cl_res_state);
124 spin_unlock(&clp->cl_lock); 125 spin_unlock(&clp->cl_lock);
125} 126}
126 127
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 97cfb143e09f..665949d27798 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -883,13 +883,15 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
883 goto out_free; 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 if (!s->s_root) { 891 if (!s->s_root) {
887 /* initial superblock/root creation */ 892 /* initial superblock/root creation */
888 s->s_flags = flags; 893 s->s_flags = flags;
889
890 nfs4_fill_super(s); 894 nfs4_fill_super(s);
891 } else {
892 nfs_free_server(server);
893 } 895 }
894 896
895 mntroot = nfs4_get_root(s, &mntfh); 897 mntroot = nfs4_get_root(s, &mntfh);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 6d0be0efd1b5..7ccfc7ef0a83 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -19,6 +19,7 @@ struct nfs_client {
19#define NFS_CS_RPCIOD 0 /* - rpciod started */ 19#define NFS_CS_RPCIOD 0 /* - rpciod started */
20#define NFS_CS_CALLBACK 1 /* - callback started */ 20#define NFS_CS_CALLBACK 1 /* - callback started */
21#define NFS_CS_IDMAP 2 /* - idmap started */ 21#define NFS_CS_IDMAP 2 /* - idmap started */
22#define NFS_CS_RENEWD 3 /* - renewd started */
22 struct sockaddr_in cl_addr; /* server identifier */ 23 struct sockaddr_in cl_addr; /* server identifier */
23 char * cl_hostname; /* hostname of server */ 24 char * cl_hostname; /* hostname of server */
24 struct list_head cl_share_link; /* link in global client list */ 25 struct list_head cl_share_link; /* link in global client list */