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