xref: /openbmc/linux/fs/nfsd/auth.c (revision 207f135d)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
27663dacdSJ. Bruce Fields /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */
31da177e4SLinus Torvalds 
41da177e4SLinus Torvalds #include <linux/sched.h>
59a74af21SBoaz Harrosh #include "nfsd.h"
6a254b246SHarvey Harrison #include "auth.h"
71da177e4SLinus Torvalds 
nfsexp_flags(struct svc_rqst * rqstp,struct svc_export * exp)8c7d51402SJ. Bruce Fields int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
91269bc69SJ. Bruce Fields {
101269bc69SJ. Bruce Fields 	struct exp_flavor_info *f;
111269bc69SJ. Bruce Fields 	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
121269bc69SJ. Bruce Fields 
131269bc69SJ. Bruce Fields 	for (f = exp->ex_flavors; f < end; f++) {
14d5497fc6SJ. Bruce Fields 		if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
151269bc69SJ. Bruce Fields 			return f->flags;
161269bc69SJ. Bruce Fields 	}
171269bc69SJ. Bruce Fields 	return exp->ex_flags;
181269bc69SJ. Bruce Fields 
191269bc69SJ. Bruce Fields }
201269bc69SJ. Bruce Fields 
nfsd_setuser(struct svc_rqst * rqstp,struct svc_export * exp)211da177e4SLinus Torvalds int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
221da177e4SLinus Torvalds {
23d84f4f99SDavid Howells 	struct group_info *rqgi;
24d84f4f99SDavid Howells 	struct group_info *gi;
25d84f4f99SDavid Howells 	struct cred *new;
261da177e4SLinus Torvalds 	int i;
271269bc69SJ. Bruce Fields 	int flags = nfsexp_flags(rqstp, exp);
281da177e4SLinus Torvalds 
293b11a1deSDavid Howells 	/* discard any old override before preparing the new set */
30ae4b884fSJeff Layton 	revert_creds(get_cred(current_real_cred()));
31d84f4f99SDavid Howells 	new = prepare_creds();
32d84f4f99SDavid Howells 	if (!new)
33d84f4f99SDavid Howells 		return -ENOMEM;
34d84f4f99SDavid Howells 
35d84f4f99SDavid Howells 	new->fsuid = rqstp->rq_cred.cr_uid;
36d84f4f99SDavid Howells 	new->fsgid = rqstp->rq_cred.cr_gid;
37d84f4f99SDavid Howells 
38d84f4f99SDavid Howells 	rqgi = rqstp->rq_cred.cr_group_info;
39d84f4f99SDavid Howells 
401269bc69SJ. Bruce Fields 	if (flags & NFSEXP_ALLSQUASH) {
41d84f4f99SDavid Howells 		new->fsuid = exp->ex_anon_uid;
42d84f4f99SDavid Howells 		new->fsgid = exp->ex_anon_gid;
43d84f4f99SDavid Howells 		gi = groups_alloc(0);
44bf935a78SJ. Bruce Fields 		if (!gi)
45bf935a78SJ. Bruce Fields 			goto oom;
461269bc69SJ. Bruce Fields 	} else if (flags & NFSEXP_ROOTSQUASH) {
476fab8779SEric W. Biederman 		if (uid_eq(new->fsuid, GLOBAL_ROOT_UID))
48d84f4f99SDavid Howells 			new->fsuid = exp->ex_anon_uid;
496fab8779SEric W. Biederman 		if (gid_eq(new->fsgid, GLOBAL_ROOT_GID))
50d84f4f99SDavid Howells 			new->fsgid = exp->ex_anon_gid;
51d84f4f99SDavid Howells 
52d84f4f99SDavid Howells 		gi = groups_alloc(rqgi->ngroups);
53d84f4f99SDavid Howells 		if (!gi)
54d84f4f99SDavid Howells 			goto oom;
55d84f4f99SDavid Howells 
56d84f4f99SDavid Howells 		for (i = 0; i < rqgi->ngroups; i++) {
5781243eacSAlexey Dobriyan 			if (gid_eq(GLOBAL_ROOT_GID, rqgi->gid[i]))
5881243eacSAlexey Dobriyan 				gi->gid[i] = exp->ex_anon_gid;
591da177e4SLinus Torvalds 			else
6081243eacSAlexey Dobriyan 				gi->gid[i] = rqgi->gid[i];
6119952667SBen Hutchings 		}
62bdcf0a42SThiago Rafael Becker 
63bdcf0a42SThiago Rafael Becker 		/* Each thread allocates its own gi, no race */
64bdcf0a42SThiago Rafael Becker 		groups_sort(gi);
651da177e4SLinus Torvalds 	} else {
66d84f4f99SDavid Howells 		gi = get_group_info(rqgi);
671da177e4SLinus Torvalds 	}
68d84f4f99SDavid Howells 
696fab8779SEric W. Biederman 	if (uid_eq(new->fsuid, INVALID_UID))
70d84f4f99SDavid Howells 		new->fsuid = exp->ex_anon_uid;
716fab8779SEric W. Biederman 	if (gid_eq(new->fsgid, INVALID_GID))
72d84f4f99SDavid Howells 		new->fsgid = exp->ex_anon_gid;
73d84f4f99SDavid Howells 
748f6c5ffcSWang YanQing 	set_groups(new, gi);
75d84f4f99SDavid Howells 	put_group_info(gi);
76d84f4f99SDavid Howells 
776fab8779SEric W. Biederman 	if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID))
78d84f4f99SDavid Howells 		new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
79d84f4f99SDavid Howells 	else
80d84f4f99SDavid Howells 		new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
81d84f4f99SDavid Howells 							new->cap_permitted);
823b11a1deSDavid Howells 	put_cred(override_creds(new));
83b914152aSJ. Bruce Fields 	put_cred(new);
843b11a1deSDavid Howells 	return 0;
85d84f4f99SDavid Howells 
86d84f4f99SDavid Howells oom:
87d84f4f99SDavid Howells 	abort_creds(new);
8861a27f08SKinglong Mee 	return -ENOMEM;
891da177e4SLinus Torvalds }
90b6dff3ecSDavid Howells 
91