diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/auth.c | 95 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 9 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 72 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 16 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 11 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 9 |
7 files changed, 137 insertions, 77 deletions
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 294992e9bf69..0184fe9b514c 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -27,53 +27,70 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) | |||
27 | 27 | ||
28 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | 28 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) |
29 | { | 29 | { |
30 | struct svc_cred cred = rqstp->rq_cred; | 30 | struct group_info *rqgi; |
31 | struct group_info *gi; | ||
32 | struct cred *new; | ||
31 | int i; | 33 | int i; |
32 | int flags = nfsexp_flags(rqstp, exp); | 34 | int flags = nfsexp_flags(rqstp, exp); |
33 | int ret; | 35 | int ret; |
34 | 36 | ||
37 | /* discard any old override before preparing the new set */ | ||
38 | revert_creds(get_cred(current->real_cred)); | ||
39 | new = prepare_creds(); | ||
40 | if (!new) | ||
41 | return -ENOMEM; | ||
42 | |||
43 | new->fsuid = rqstp->rq_cred.cr_uid; | ||
44 | new->fsgid = rqstp->rq_cred.cr_gid; | ||
45 | |||
46 | rqgi = rqstp->rq_cred.cr_group_info; | ||
47 | |||
35 | if (flags & NFSEXP_ALLSQUASH) { | 48 | if (flags & NFSEXP_ALLSQUASH) { |
36 | cred.cr_uid = exp->ex_anon_uid; | 49 | new->fsuid = exp->ex_anon_uid; |
37 | cred.cr_gid = exp->ex_anon_gid; | 50 | new->fsgid = exp->ex_anon_gid; |
38 | cred.cr_group_info = groups_alloc(0); | 51 | gi = groups_alloc(0); |
39 | } else if (flags & NFSEXP_ROOTSQUASH) { | 52 | } else if (flags & NFSEXP_ROOTSQUASH) { |
40 | struct group_info *gi; | 53 | if (!new->fsuid) |
41 | if (!cred.cr_uid) | 54 | new->fsuid = exp->ex_anon_uid; |
42 | cred.cr_uid = exp->ex_anon_uid; | 55 | if (!new->fsgid) |
43 | if (!cred.cr_gid) | 56 | new->fsgid = exp->ex_anon_gid; |
44 | cred.cr_gid = exp->ex_anon_gid; | ||
45 | gi = groups_alloc(cred.cr_group_info->ngroups); | ||
46 | if (gi) | ||
47 | for (i = 0; i < cred.cr_group_info->ngroups; i++) { | ||
48 | if (!GROUP_AT(cred.cr_group_info, i)) | ||
49 | GROUP_AT(gi, i) = exp->ex_anon_gid; | ||
50 | else | ||
51 | GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i); | ||
52 | } | ||
53 | cred.cr_group_info = gi; | ||
54 | } else | ||
55 | get_group_info(cred.cr_group_info); | ||
56 | |||
57 | if (cred.cr_uid != (uid_t) -1) | ||
58 | current->fsuid = cred.cr_uid; | ||
59 | else | ||
60 | current->fsuid = exp->ex_anon_uid; | ||
61 | if (cred.cr_gid != (gid_t) -1) | ||
62 | current->fsgid = cred.cr_gid; | ||
63 | else | ||
64 | current->fsgid = exp->ex_anon_gid; | ||
65 | 57 | ||
66 | if (!cred.cr_group_info) | 58 | gi = groups_alloc(rqgi->ngroups); |
67 | return -ENOMEM; | 59 | if (!gi) |
68 | ret = set_current_groups(cred.cr_group_info); | 60 | goto oom; |
69 | put_group_info(cred.cr_group_info); | 61 | |
70 | if ((cred.cr_uid)) { | 62 | for (i = 0; i < rqgi->ngroups; i++) { |
71 | current->cap_effective = | 63 | if (!GROUP_AT(rqgi, i)) |
72 | cap_drop_nfsd_set(current->cap_effective); | 64 | GROUP_AT(gi, i) = exp->ex_anon_gid; |
65 | else | ||
66 | GROUP_AT(gi, i) = GROUP_AT(rqgi, i); | ||
67 | } | ||
73 | } else { | 68 | } else { |
74 | current->cap_effective = | 69 | gi = get_group_info(rqgi); |
75 | cap_raise_nfsd_set(current->cap_effective, | ||
76 | current->cap_permitted); | ||
77 | } | 70 | } |
71 | |||
72 | if (new->fsuid == (uid_t) -1) | ||
73 | new->fsuid = exp->ex_anon_uid; | ||
74 | if (new->fsgid == (gid_t) -1) | ||
75 | new->fsgid = exp->ex_anon_gid; | ||
76 | |||
77 | ret = set_groups(new, gi); | ||
78 | put_group_info(gi); | ||
79 | if (!ret) | ||
80 | goto error; | ||
81 | |||
82 | if (new->uid) | ||
83 | new->cap_effective = cap_drop_nfsd_set(new->cap_effective); | ||
84 | else | ||
85 | new->cap_effective = cap_raise_nfsd_set(new->cap_effective, | ||
86 | new->cap_permitted); | ||
87 | put_cred(override_creds(new)); | ||
88 | return 0; | ||
89 | |||
90 | oom: | ||
91 | ret = -ENOMEM; | ||
92 | error: | ||
93 | abort_creds(new); | ||
78 | return ret; | 94 | return ret; |
79 | } | 95 | } |
96 | |||
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 094747a1227c..6d7d8c02c197 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -358,6 +358,7 @@ static struct rpc_program cb_program = { | |||
358 | .nrvers = ARRAY_SIZE(nfs_cb_version), | 358 | .nrvers = ARRAY_SIZE(nfs_cb_version), |
359 | .version = nfs_cb_version, | 359 | .version = nfs_cb_version, |
360 | .stats = &cb_stats, | 360 | .stats = &cb_stats, |
361 | .pipe_dir_name = "/nfsd4_cb", | ||
361 | }; | 362 | }; |
362 | 363 | ||
363 | /* Reference counting, callback cleanup, etc., all look racy as heck. | 364 | /* Reference counting, callback cleanup, etc., all look racy as heck. |
@@ -382,8 +383,9 @@ static int do_probe_callback(void *data) | |||
382 | .program = &cb_program, | 383 | .program = &cb_program, |
383 | .prognumber = cb->cb_prog, | 384 | .prognumber = cb->cb_prog, |
384 | .version = nfs_cb_version[1]->number, | 385 | .version = nfs_cb_version[1]->number, |
385 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | 386 | .authflavor = clp->cl_flavor, |
386 | .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), | 387 | .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), |
388 | .client_name = clp->cl_principal, | ||
387 | }; | 389 | }; |
388 | struct rpc_message msg = { | 390 | struct rpc_message msg = { |
389 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | 391 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], |
@@ -392,6 +394,11 @@ static int do_probe_callback(void *data) | |||
392 | struct rpc_clnt *client; | 394 | struct rpc_clnt *client; |
393 | int status; | 395 | int status; |
394 | 396 | ||
397 | if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) { | ||
398 | status = nfserr_cb_path_down; | ||
399 | goto out_err; | ||
400 | } | ||
401 | |||
395 | /* Initialize address */ | 402 | /* Initialize address */ |
396 | memset(&addr, 0, sizeof(addr)); | 403 | memset(&addr, 0, sizeof(addr)); |
397 | addr.sin_family = AF_INET; | 404 | addr.sin_family = AF_INET; |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index b79ec930d9f1..0f9d6efaa62b 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->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 | ||
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->fsuid = saveuid; | 76 | revert_creds(original); |
70 | current->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,26 +218,29 @@ 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 | INIT_LIST_HEAD(dentries); | 236 | INIT_LIST_HEAD(dentries); |
229 | 237 | ||
230 | 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()); | ||
231 | status = PTR_ERR(filp); | 240 | status = PTR_ERR(filp); |
232 | if (IS_ERR(filp)) | 241 | if (IS_ERR(filp)) |
233 | goto out; | 242 | goto out; |
243 | INIT_LIST_HEAD(dentries); | ||
234 | status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla); | 244 | status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla); |
235 | fput(filp); | 245 | fput(filp); |
236 | while (!list_empty(dentries)) { | 246 | while (!list_empty(dentries)) { |
@@ -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: | |||
311 | void | 321 | void |
312 | nfsd4_remove_clid_dir(struct nfs4_client *clp) | 322 | nfsd4_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) { | |||
401 | void | 414 | void |
402 | nfsd4_init_recdir(char *rec_dirname) | 415 | nfsd4_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 | ||
426 | void | 444 | void |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1a052ac2bde9..13e0e074dbb8 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
55 | #include <linux/lockd/bind.h> | 55 | #include <linux/lockd/bind.h> |
56 | #include <linux/module.h> | 56 | #include <linux/module.h> |
57 | #include <linux/sunrpc/svcauth_gss.h> | ||
57 | 58 | ||
58 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 59 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
59 | 60 | ||
@@ -377,6 +378,7 @@ free_client(struct nfs4_client *clp) | |||
377 | shutdown_callback_client(clp); | 378 | shutdown_callback_client(clp); |
378 | if (clp->cl_cred.cr_group_info) | 379 | if (clp->cl_cred.cr_group_info) |
379 | put_group_info(clp->cl_cred.cr_group_info); | 380 | put_group_info(clp->cl_cred.cr_group_info); |
381 | kfree(clp->cl_principal); | ||
380 | kfree(clp->cl_name.data); | 382 | kfree(clp->cl_name.data); |
381 | kfree(clp); | 383 | kfree(clp); |
382 | } | 384 | } |
@@ -696,6 +698,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
696 | unsigned int strhashval; | 698 | unsigned int strhashval; |
697 | struct nfs4_client *conf, *unconf, *new; | 699 | struct nfs4_client *conf, *unconf, *new; |
698 | __be32 status; | 700 | __be32 status; |
701 | char *princ; | ||
699 | char dname[HEXDIR_LEN]; | 702 | char dname[HEXDIR_LEN]; |
700 | 703 | ||
701 | if (!check_name(clname)) | 704 | if (!check_name(clname)) |
@@ -719,8 +722,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
719 | status = nfserr_clid_inuse; | 722 | status = nfserr_clid_inuse; |
720 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) | 723 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) |
721 | || conf->cl_addr != sin->sin_addr.s_addr) { | 724 | || conf->cl_addr != sin->sin_addr.s_addr) { |
722 | dprintk("NFSD: setclientid: string in use by client" | 725 | dprintk("NFSD: setclientid: string in use by clientat %pI4\n", |
723 | "at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr)); | 726 | &conf->cl_addr); |
724 | goto out; | 727 | goto out; |
725 | } | 728 | } |
726 | } | 729 | } |
@@ -783,6 +786,15 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
783 | } | 786 | } |
784 | copy_verf(new, &clverifier); | 787 | copy_verf(new, &clverifier); |
785 | new->cl_addr = sin->sin_addr.s_addr; | 788 | new->cl_addr = sin->sin_addr.s_addr; |
789 | new->cl_flavor = rqstp->rq_flavor; | ||
790 | princ = svc_gss_principal(rqstp); | ||
791 | if (princ) { | ||
792 | new->cl_principal = kstrdup(princ, GFP_KERNEL); | ||
793 | if (new->cl_principal == NULL) { | ||
794 | free_client(new); | ||
795 | goto out; | ||
796 | } | ||
797 | } | ||
786 | copy_cred(&new->cl_cred, &rqstp->rq_cred); | 798 | copy_cred(&new->cl_cred, &rqstp->rq_cred); |
787 | gen_confirm(new); | 799 | gen_confirm(new); |
788 | gen_callback(new, setclid); | 800 | gen_callback(new, setclid); |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index e3f9783fdcf7..77d7b8c531a6 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -330,7 +330,7 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) | |||
330 | return -EINVAL; | 330 | return -EINVAL; |
331 | 331 | ||
332 | /* get ipv4 address */ | 332 | /* get ipv4 address */ |
333 | if (sscanf(fo_path, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) != 4) | 333 | if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4) |
334 | return -EINVAL; | 334 | return -EINVAL; |
335 | if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255) | 335 | if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255) |
336 | return -EINVAL; | 336 | return -EINVAL; |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index cd25d91895a1..f0da7d9c3a92 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -186,9 +186,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
186 | * access control settings being in effect, we cannot | 186 | * access control settings being in effect, we cannot |
187 | * fix that case easily. | 187 | * fix that case easily. |
188 | */ | 188 | */ |
189 | current->cap_effective = | 189 | struct cred *new = prepare_creds(); |
190 | cap_raise_nfsd_set(current->cap_effective, | 190 | if (!new) |
191 | current->cap_permitted); | 191 | return nfserrno(-ENOMEM); |
192 | new->cap_effective = | ||
193 | cap_raise_nfsd_set(new->cap_effective, | ||
194 | new->cap_permitted); | ||
195 | put_cred(override_creds(new)); | ||
196 | put_cred(new); | ||
192 | } else { | 197 | } else { |
193 | error = nfsd_setuser_and_check_port(rqstp, exp); | 198 | error = nfsd_setuser_and_check_port(rqstp, exp); |
194 | if (error) | 199 | if (error) |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4433c8f00163..d1c5f787b365 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -671,6 +671,7 @@ __be32 | |||
671 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | 671 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, |
672 | int access, struct file **filp) | 672 | int access, struct file **filp) |
673 | { | 673 | { |
674 | const struct cred *cred = current_cred(); | ||
674 | struct dentry *dentry; | 675 | struct dentry *dentry; |
675 | struct inode *inode; | 676 | struct inode *inode; |
676 | int flags = O_RDONLY|O_LARGEFILE; | 677 | int flags = O_RDONLY|O_LARGEFILE; |
@@ -725,7 +726,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
725 | DQUOT_INIT(inode); | 726 | DQUOT_INIT(inode); |
726 | } | 727 | } |
727 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), | 728 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), |
728 | flags); | 729 | flags, cred); |
729 | if (IS_ERR(*filp)) | 730 | if (IS_ERR(*filp)) |
730 | host_err = PTR_ERR(*filp); | 731 | host_err = PTR_ERR(*filp); |
731 | out_nfserr: | 732 | out_nfserr: |
@@ -1169,7 +1170,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp, | |||
1169 | * send along the gid on create when it tries to implement | 1170 | * send along the gid on create when it tries to implement |
1170 | * setgid directories via NFS: | 1171 | * setgid directories via NFS: |
1171 | */ | 1172 | */ |
1172 | if (current->fsuid != 0) | 1173 | if (current_fsuid() != 0) |
1173 | iap->ia_valid &= ~(ATTR_UID|ATTR_GID); | 1174 | iap->ia_valid &= ~(ATTR_UID|ATTR_GID); |
1174 | if (iap->ia_valid) | 1175 | if (iap->ia_valid) |
1175 | return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1176 | return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); |
@@ -2001,7 +2002,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2001 | IS_APPEND(inode)? " append" : "", | 2002 | IS_APPEND(inode)? " append" : "", |
2002 | __mnt_is_readonly(exp->ex_path.mnt)? " ro" : ""); | 2003 | __mnt_is_readonly(exp->ex_path.mnt)? " ro" : ""); |
2003 | dprintk(" owner %d/%d user %d/%d\n", | 2004 | dprintk(" owner %d/%d user %d/%d\n", |
2004 | inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); | 2005 | inode->i_uid, inode->i_gid, current_fsuid(), current_fsgid()); |
2005 | #endif | 2006 | #endif |
2006 | 2007 | ||
2007 | /* Normally we reject any write/sattr etc access on a read-only file | 2008 | /* Normally we reject any write/sattr etc access on a read-only file |
@@ -2044,7 +2045,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2044 | * with NFSv3. | 2045 | * with NFSv3. |
2045 | */ | 2046 | */ |
2046 | if ((acc & NFSD_MAY_OWNER_OVERRIDE) && | 2047 | if ((acc & NFSD_MAY_OWNER_OVERRIDE) && |
2047 | inode->i_uid == current->fsuid) | 2048 | inode->i_uid == current_fsuid()) |
2048 | return 0; | 2049 | return 0; |
2049 | 2050 | ||
2050 | /* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */ | 2051 | /* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */ |