diff options
Diffstat (limited to 'fs/nfsd/nfs4recover.c')
-rw-r--r-- | fs/nfsd/nfs4recover.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 632a50b4b371..9371ea12d7fa 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -54,20 +54,26 @@ | |||
54 | static struct path rec_dir; | 54 | static struct path rec_dir; |
55 | static int rec_dir_init = 0; | 55 | static int rec_dir_init = 0; |
56 | 56 | ||
57 | static void | 57 | static int |
58 | nfs4_save_user(uid_t *saveuid, gid_t *savegid) | 58 | nfs4_save_creds(const struct cred **original_creds) |
59 | { | 59 | { |
60 | *saveuid = current->cred->fsuid; | 60 | struct cred *new; |
61 | *savegid = current->cred->fsgid; | 61 | |
62 | current->cred->fsuid = 0; | 62 | new = prepare_creds(); |
63 | current->cred->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 | ||
66 | static void | 73 | static void |
67 | nfs4_reset_user(uid_t saveuid, gid_t savegid) | 74 | nfs4_reset_creds(const struct cred *original) |
68 | { | 75 | { |
69 | current->cred->fsuid = saveuid; | 76 | revert_creds(original); |
70 | current->cred->fsgid = savegid; | ||
71 | } | 77 | } |
72 | 78 | ||
73 | static void | 79 | static void |
@@ -129,10 +135,9 @@ nfsd4_sync_rec_dir(void) | |||
129 | int | 135 | int |
130 | nfsd4_create_clid_dir(struct nfs4_client *clp) | 136 | nfsd4_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,20 +218,21 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen, | |||
211 | static int | 218 | static int |
212 | nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) | 219 | nfsd4_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; | ||
228 | 236 | ||
229 | filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY, | 237 | filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY, |
230 | current_cred()); | 238 | current_cred()); |
@@ -250,7 +258,7 @@ out: | |||
250 | dput(child->dentry); | 258 | dput(child->dentry); |
251 | kfree(child); | 259 | kfree(child); |
252 | } | 260 | } |
253 | nfs4_reset_user(uid, gid); | 261 | nfs4_reset_creds(original_cred); |
254 | return status; | 262 | return status; |
255 | } | 263 | } |
256 | 264 | ||
@@ -312,8 +320,7 @@ out: | |||
312 | void | 320 | void |
313 | nfsd4_remove_clid_dir(struct nfs4_client *clp) | 321 | nfsd4_remove_clid_dir(struct nfs4_client *clp) |
314 | { | 322 | { |
315 | uid_t uid; | 323 | const struct cred *original_cred; |
316 | gid_t gid; | ||
317 | int status; | 324 | int status; |
318 | 325 | ||
319 | if (!rec_dir_init || !clp->cl_firststate) | 326 | if (!rec_dir_init || !clp->cl_firststate) |
@@ -323,9 +330,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
323 | if (status) | 330 | if (status) |
324 | goto out; | 331 | goto out; |
325 | clp->cl_firststate = 0; | 332 | clp->cl_firststate = 0; |
326 | nfs4_save_user(&uid, &gid); | 333 | |
334 | status = nfs4_save_creds(&original_cred); | ||
335 | if (status < 0) | ||
336 | goto out; | ||
337 | |||
327 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); | 338 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); |
328 | nfs4_reset_user(uid, gid); | 339 | nfs4_reset_creds(original_cred); |
329 | if (status == 0) | 340 | if (status == 0) |
330 | nfsd4_sync_rec_dir(); | 341 | nfsd4_sync_rec_dir(); |
331 | mnt_drop_write(rec_dir.mnt); | 342 | mnt_drop_write(rec_dir.mnt); |
@@ -402,16 +413,21 @@ nfsd4_recdir_load(void) { | |||
402 | void | 413 | void |
403 | nfsd4_init_recdir(char *rec_dirname) | 414 | nfsd4_init_recdir(char *rec_dirname) |
404 | { | 415 | { |
405 | uid_t uid = 0; | 416 | const struct cred *original_cred; |
406 | gid_t gid = 0; | 417 | int status; |
407 | int status; | ||
408 | 418 | ||
409 | printk("NFSD: Using %s as the NFSv4 state recovery directory\n", | 419 | printk("NFSD: Using %s as the NFSv4 state recovery directory\n", |
410 | rec_dirname); | 420 | rec_dirname); |
411 | 421 | ||
412 | BUG_ON(rec_dir_init); | 422 | BUG_ON(rec_dir_init); |
413 | 423 | ||
414 | nfs4_save_user(&uid, &gid); | 424 | status = nfs4_save_creds(&original_cred); |
425 | if (status < 0) { | ||
426 | printk("NFSD: Unable to change credentials to find recovery" | ||
427 | " directory: error %d\n", | ||
428 | status); | ||
429 | return; | ||
430 | } | ||
415 | 431 | ||
416 | status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, | 432 | status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, |
417 | &rec_dir); | 433 | &rec_dir); |
@@ -421,7 +437,7 @@ nfsd4_init_recdir(char *rec_dirname) | |||
421 | 437 | ||
422 | if (!status) | 438 | if (!status) |
423 | rec_dir_init = 1; | 439 | rec_dir_init = 1; |
424 | nfs4_reset_user(uid, gid); | 440 | nfs4_reset_creds(original_cred); |
425 | } | 441 | } |
426 | 442 | ||
427 | void | 443 | void |