]>
Commit | Line | Data |
---|---|---|
1 | /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ | |
2 | ||
3 | #include <linux/sched.h> | |
4 | #include "nfsd.h" | |
5 | #include "auth.h" | |
6 | ||
7 | int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) | |
8 | { | |
9 | struct exp_flavor_info *f; | |
10 | struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; | |
11 | ||
12 | for (f = exp->ex_flavors; f < end; f++) { | |
13 | if (f->pseudoflavor == rqstp->rq_cred.cr_flavor) | |
14 | return f->flags; | |
15 | } | |
16 | return exp->ex_flags; | |
17 | ||
18 | } | |
19 | ||
20 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | |
21 | { | |
22 | struct group_info *rqgi; | |
23 | struct group_info *gi; | |
24 | struct cred *new; | |
25 | int i; | |
26 | int flags = nfsexp_flags(rqstp, exp); | |
27 | ||
28 | validate_process_creds(); | |
29 | ||
30 | /* discard any old override before preparing the new set */ | |
31 | revert_creds(get_cred(current_real_cred())); | |
32 | new = prepare_creds(); | |
33 | if (!new) | |
34 | return -ENOMEM; | |
35 | ||
36 | new->fsuid = rqstp->rq_cred.cr_uid; | |
37 | new->fsgid = rqstp->rq_cred.cr_gid; | |
38 | ||
39 | rqgi = rqstp->rq_cred.cr_group_info; | |
40 | ||
41 | if (flags & NFSEXP_ALLSQUASH) { | |
42 | new->fsuid = exp->ex_anon_uid; | |
43 | new->fsgid = exp->ex_anon_gid; | |
44 | gi = groups_alloc(0); | |
45 | if (!gi) | |
46 | goto oom; | |
47 | } else if (flags & NFSEXP_ROOTSQUASH) { | |
48 | if (uid_eq(new->fsuid, GLOBAL_ROOT_UID)) | |
49 | new->fsuid = exp->ex_anon_uid; | |
50 | if (gid_eq(new->fsgid, GLOBAL_ROOT_GID)) | |
51 | new->fsgid = exp->ex_anon_gid; | |
52 | ||
53 | gi = groups_alloc(rqgi->ngroups); | |
54 | if (!gi) | |
55 | goto oom; | |
56 | ||
57 | for (i = 0; i < rqgi->ngroups; i++) { | |
58 | if (gid_eq(GLOBAL_ROOT_GID, rqgi->gid[i])) | |
59 | gi->gid[i] = exp->ex_anon_gid; | |
60 | else | |
61 | gi->gid[i] = rqgi->gid[i]; | |
62 | } | |
63 | } else { | |
64 | gi = get_group_info(rqgi); | |
65 | } | |
66 | ||
67 | if (uid_eq(new->fsuid, INVALID_UID)) | |
68 | new->fsuid = exp->ex_anon_uid; | |
69 | if (gid_eq(new->fsgid, INVALID_GID)) | |
70 | new->fsgid = exp->ex_anon_gid; | |
71 | ||
72 | set_groups(new, gi); | |
73 | put_group_info(gi); | |
74 | ||
75 | if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID)) | |
76 | new->cap_effective = cap_drop_nfsd_set(new->cap_effective); | |
77 | else | |
78 | new->cap_effective = cap_raise_nfsd_set(new->cap_effective, | |
79 | new->cap_permitted); | |
80 | validate_process_creds(); | |
81 | put_cred(override_creds(new)); | |
82 | put_cred(new); | |
83 | validate_process_creds(); | |
84 | return 0; | |
85 | ||
86 | oom: | |
87 | abort_creds(new); | |
88 | return -ENOMEM; | |
89 | } | |
90 |