aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4recover.c')
-rw-r--r--fs/nfsd/nfs4recover.c72
1 files changed, 45 insertions, 27 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index bb93946ace22..0f9d6efaa62b 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -54,20 +54,26 @@
54static struct path rec_dir; 54static struct path rec_dir;
55static int rec_dir_init = 0; 55static int rec_dir_init = 0;
56 56
57static void 57static int
58nfs4_save_user(uid_t *saveuid, gid_t *savegid) 58nfs4_save_creds(const struct cred **original_creds)
59{ 59{
60 *saveuid = current->fsuid; 60 struct cred *new;
61 *savegid = current->fsgid; 61
62 current->fsuid = 0; 62 new = prepare_creds();
63 current->fsgid = 0; 63 if (!new)
64 return -ENOMEM;
65
66 new->fsuid = 0;
67 new->fsgid = 0;
68 *original_creds = override_creds(new);
69 put_cred(new);
70 return 0;
64} 71}
65 72
66static void 73static void
67nfs4_reset_user(uid_t saveuid, gid_t savegid) 74nfs4_reset_creds(const struct cred *original)
68{ 75{
69 current->fsuid = saveuid; 76 revert_creds(original);
70 current->fsgid = savegid;
71} 77}
72 78
73static void 79static void
@@ -129,10 +135,9 @@ nfsd4_sync_rec_dir(void)
129int 135int
130nfsd4_create_clid_dir(struct nfs4_client *clp) 136nfsd4_create_clid_dir(struct nfs4_client *clp)
131{ 137{
138 const struct cred *original_cred;
132 char *dname = clp->cl_recdir; 139 char *dname = clp->cl_recdir;
133 struct dentry *dentry; 140 struct dentry *dentry;
134 uid_t uid;
135 gid_t gid;
136 int status; 141 int status;
137 142
138 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 143 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
@@ -140,7 +145,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
140 if (!rec_dir_init || clp->cl_firststate) 145 if (!rec_dir_init || clp->cl_firststate)
141 return 0; 146 return 0;
142 147
143 nfs4_save_user(&uid, &gid); 148 status = nfs4_save_creds(&original_cred);
149 if (status < 0)
150 return status;
144 151
145 /* lock the parent */ 152 /* lock the parent */
146 mutex_lock(&rec_dir.dentry->d_inode->i_mutex); 153 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
@@ -168,7 +175,7 @@ out_unlock:
168 clp->cl_firststate = 1; 175 clp->cl_firststate = 1;
169 nfsd4_sync_rec_dir(); 176 nfsd4_sync_rec_dir();
170 } 177 }
171 nfs4_reset_user(uid, gid); 178 nfs4_reset_creds(original_cred);
172 dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); 179 dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
173 return status; 180 return status;
174} 181}
@@ -211,22 +218,25 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
211static int 218static int
212nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) 219nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
213{ 220{
221 const struct cred *original_cred;
214 struct file *filp; 222 struct file *filp;
215 struct dentry_list_arg dla = { 223 struct dentry_list_arg dla = {
216 .parent = dir, 224 .parent = dir,
217 }; 225 };
218 struct list_head *dentries = &dla.dentries; 226 struct list_head *dentries = &dla.dentries;
219 struct dentry_list *child; 227 struct dentry_list *child;
220 uid_t uid;
221 gid_t gid;
222 int status; 228 int status;
223 229
224 if (!rec_dir_init) 230 if (!rec_dir_init)
225 return 0; 231 return 0;
226 232
227 nfs4_save_user(&uid, &gid); 233 status = nfs4_save_creds(&original_cred);
234 if (status < 0)
235 return status;
236 INIT_LIST_HEAD(dentries);
228 237
229 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY); 238 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
239 current_cred());
230 status = PTR_ERR(filp); 240 status = PTR_ERR(filp);
231 if (IS_ERR(filp)) 241 if (IS_ERR(filp))
232 goto out; 242 goto out;
@@ -249,7 +259,7 @@ out:
249 dput(child->dentry); 259 dput(child->dentry);
250 kfree(child); 260 kfree(child);
251 } 261 }
252 nfs4_reset_user(uid, gid); 262 nfs4_reset_creds(original_cred);
253 return status; 263 return status;
254} 264}
255 265
@@ -311,8 +321,7 @@ out:
311void 321void
312nfsd4_remove_clid_dir(struct nfs4_client *clp) 322nfsd4_remove_clid_dir(struct nfs4_client *clp)
313{ 323{
314 uid_t uid; 324 const struct cred *original_cred;
315 gid_t gid;
316 int status; 325 int status;
317 326
318 if (!rec_dir_init || !clp->cl_firststate) 327 if (!rec_dir_init || !clp->cl_firststate)
@@ -322,9 +331,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
322 if (status) 331 if (status)
323 goto out; 332 goto out;
324 clp->cl_firststate = 0; 333 clp->cl_firststate = 0;
325 nfs4_save_user(&uid, &gid); 334
335 status = nfs4_save_creds(&original_cred);
336 if (status < 0)
337 goto out;
338
326 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); 339 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
327 nfs4_reset_user(uid, gid); 340 nfs4_reset_creds(original_cred);
328 if (status == 0) 341 if (status == 0)
329 nfsd4_sync_rec_dir(); 342 nfsd4_sync_rec_dir();
330 mnt_drop_write(rec_dir.mnt); 343 mnt_drop_write(rec_dir.mnt);
@@ -401,16 +414,21 @@ nfsd4_recdir_load(void) {
401void 414void
402nfsd4_init_recdir(char *rec_dirname) 415nfsd4_init_recdir(char *rec_dirname)
403{ 416{
404 uid_t uid = 0; 417 const struct cred *original_cred;
405 gid_t gid = 0; 418 int status;
406 int status;
407 419
408 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 420 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
409 rec_dirname); 421 rec_dirname);
410 422
411 BUG_ON(rec_dir_init); 423 BUG_ON(rec_dir_init);
412 424
413 nfs4_save_user(&uid, &gid); 425 status = nfs4_save_creds(&original_cred);
426 if (status < 0) {
427 printk("NFSD: Unable to change credentials to find recovery"
428 " directory: error %d\n",
429 status);
430 return;
431 }
414 432
415 status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, 433 status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
416 &rec_dir); 434 &rec_dir);
@@ -420,7 +438,7 @@ nfsd4_init_recdir(char *rec_dirname)
420 438
421 if (!status) 439 if (!status)
422 rec_dir_init = 1; 440 rec_dir_init = 1;
423 nfs4_reset_user(uid, gid); 441 nfs4_reset_creds(original_cred);
424} 442}
425 443
426void 444void