diff options
Diffstat (limited to 'fs/nfsd/auth.c')
-rw-r--r-- | fs/nfsd/auth.c | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 808fc03a6fbd..836ffa1047d9 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -27,55 +27,67 @@ 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 cred *act_as = current->cred ; | 30 | struct group_info *rqgi; |
31 | struct svc_cred cred = rqstp->rq_cred; | 31 | struct group_info *gi; |
32 | struct cred *new; | ||
32 | int i; | 33 | int i; |
33 | int flags = nfsexp_flags(rqstp, exp); | 34 | int flags = nfsexp_flags(rqstp, exp); |
34 | int ret; | 35 | int ret; |
35 | 36 | ||
37 | new = prepare_creds(); | ||
38 | if (!new) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | new->fsuid = rqstp->rq_cred.cr_uid; | ||
42 | new->fsgid = rqstp->rq_cred.cr_gid; | ||
43 | |||
44 | rqgi = rqstp->rq_cred.cr_group_info; | ||
45 | |||
36 | if (flags & NFSEXP_ALLSQUASH) { | 46 | if (flags & NFSEXP_ALLSQUASH) { |
37 | cred.cr_uid = exp->ex_anon_uid; | 47 | new->fsuid = exp->ex_anon_uid; |
38 | cred.cr_gid = exp->ex_anon_gid; | 48 | new->fsgid = exp->ex_anon_gid; |
39 | cred.cr_group_info = groups_alloc(0); | 49 | gi = groups_alloc(0); |
40 | } else if (flags & NFSEXP_ROOTSQUASH) { | 50 | } else if (flags & NFSEXP_ROOTSQUASH) { |
41 | struct group_info *gi; | 51 | if (!new->fsuid) |
42 | if (!cred.cr_uid) | 52 | new->fsuid = exp->ex_anon_uid; |
43 | cred.cr_uid = exp->ex_anon_uid; | 53 | if (!new->fsgid) |
44 | if (!cred.cr_gid) | 54 | new->fsgid = exp->ex_anon_gid; |
45 | cred.cr_gid = exp->ex_anon_gid; | ||
46 | gi = groups_alloc(cred.cr_group_info->ngroups); | ||
47 | if (gi) | ||
48 | for (i = 0; i < cred.cr_group_info->ngroups; i++) { | ||
49 | if (!GROUP_AT(cred.cr_group_info, i)) | ||
50 | GROUP_AT(gi, i) = exp->ex_anon_gid; | ||
51 | else | ||
52 | GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i); | ||
53 | } | ||
54 | cred.cr_group_info = gi; | ||
55 | } else | ||
56 | get_group_info(cred.cr_group_info); | ||
57 | |||
58 | if (cred.cr_uid != (uid_t) -1) | ||
59 | act_as->fsuid = cred.cr_uid; | ||
60 | else | ||
61 | act_as->fsuid = exp->ex_anon_uid; | ||
62 | if (cred.cr_gid != (gid_t) -1) | ||
63 | act_as->fsgid = cred.cr_gid; | ||
64 | else | ||
65 | act_as->fsgid = exp->ex_anon_gid; | ||
66 | 55 | ||
67 | if (!cred.cr_group_info) | 56 | gi = groups_alloc(rqgi->ngroups); |
68 | return -ENOMEM; | 57 | if (!gi) |
69 | ret = set_groups(act_as, cred.cr_group_info); | 58 | goto oom; |
70 | put_group_info(cred.cr_group_info); | 59 | |
71 | if ((cred.cr_uid)) { | 60 | for (i = 0; i < rqgi->ngroups; i++) { |
72 | act_as->cap_effective = | 61 | if (!GROUP_AT(rqgi, i)) |
73 | cap_drop_nfsd_set(act_as->cap_effective); | 62 | GROUP_AT(gi, i) = exp->ex_anon_gid; |
63 | else | ||
64 | GROUP_AT(gi, i) = GROUP_AT(rqgi, i); | ||
65 | } | ||
74 | } else { | 66 | } else { |
75 | act_as->cap_effective = | 67 | gi = get_group_info(rqgi); |
76 | cap_raise_nfsd_set(act_as->cap_effective, | ||
77 | act_as->cap_permitted); | ||
78 | } | 68 | } |
69 | |||
70 | if (new->fsuid == (uid_t) -1) | ||
71 | new->fsuid = exp->ex_anon_uid; | ||
72 | if (new->fsgid == (gid_t) -1) | ||
73 | new->fsgid = exp->ex_anon_gid; | ||
74 | |||
75 | ret = set_groups(new, gi); | ||
76 | put_group_info(gi); | ||
77 | if (!ret) | ||
78 | goto error; | ||
79 | |||
80 | if (new->uid) | ||
81 | new->cap_effective = cap_drop_nfsd_set(new->cap_effective); | ||
82 | else | ||
83 | new->cap_effective = cap_raise_nfsd_set(new->cap_effective, | ||
84 | new->cap_permitted); | ||
85 | return commit_creds(new); | ||
86 | |||
87 | oom: | ||
88 | ret = -ENOMEM; | ||
89 | error: | ||
90 | abort_creds(new); | ||
79 | return ret; | 91 | return ret; |
80 | } | 92 | } |
81 | 93 | ||