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