0001
0002
0003
0004 #include <linux/sched.h>
0005 #include "nfsd.h"
0006 #include "auth.h"
0007
0008 int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
0009 {
0010 struct exp_flavor_info *f;
0011 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
0012
0013 for (f = exp->ex_flavors; f < end; f++) {
0014 if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
0015 return f->flags;
0016 }
0017 return exp->ex_flags;
0018
0019 }
0020
0021 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
0022 {
0023 struct group_info *rqgi;
0024 struct group_info *gi;
0025 struct cred *new;
0026 int i;
0027 int flags = nfsexp_flags(rqstp, exp);
0028
0029 validate_process_creds();
0030
0031
0032 revert_creds(get_cred(current_real_cred()));
0033 new = prepare_creds();
0034 if (!new)
0035 return -ENOMEM;
0036
0037 new->fsuid = rqstp->rq_cred.cr_uid;
0038 new->fsgid = rqstp->rq_cred.cr_gid;
0039
0040 rqgi = rqstp->rq_cred.cr_group_info;
0041
0042 if (flags & NFSEXP_ALLSQUASH) {
0043 new->fsuid = exp->ex_anon_uid;
0044 new->fsgid = exp->ex_anon_gid;
0045 gi = groups_alloc(0);
0046 if (!gi)
0047 goto oom;
0048 } else if (flags & NFSEXP_ROOTSQUASH) {
0049 if (uid_eq(new->fsuid, GLOBAL_ROOT_UID))
0050 new->fsuid = exp->ex_anon_uid;
0051 if (gid_eq(new->fsgid, GLOBAL_ROOT_GID))
0052 new->fsgid = exp->ex_anon_gid;
0053
0054 gi = groups_alloc(rqgi->ngroups);
0055 if (!gi)
0056 goto oom;
0057
0058 for (i = 0; i < rqgi->ngroups; i++) {
0059 if (gid_eq(GLOBAL_ROOT_GID, rqgi->gid[i]))
0060 gi->gid[i] = exp->ex_anon_gid;
0061 else
0062 gi->gid[i] = rqgi->gid[i];
0063 }
0064
0065
0066 groups_sort(gi);
0067 } else {
0068 gi = get_group_info(rqgi);
0069 }
0070
0071 if (uid_eq(new->fsuid, INVALID_UID))
0072 new->fsuid = exp->ex_anon_uid;
0073 if (gid_eq(new->fsgid, INVALID_GID))
0074 new->fsgid = exp->ex_anon_gid;
0075
0076 set_groups(new, gi);
0077 put_group_info(gi);
0078
0079 if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID))
0080 new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
0081 else
0082 new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
0083 new->cap_permitted);
0084 validate_process_creds();
0085 put_cred(override_creds(new));
0086 put_cred(new);
0087 validate_process_creds();
0088 return 0;
0089
0090 oom:
0091 abort_creds(new);
0092 return -ENOMEM;
0093 }
0094