linux/fs/nfsd/auth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */
   3
   4#include <linux/sched.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
  29        validate_process_creds();
  30
  31        /* discard any old override before preparing the new set */
  32        revert_creds(get_cred(current_real_cred()));
  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
  42        if (flags & NFSEXP_ALLSQUASH) {
  43                new->fsuid = exp->ex_anon_uid;
  44                new->fsgid = exp->ex_anon_gid;
  45                gi = groups_alloc(0);
  46                if (!gi)
  47                        goto oom;
  48        } else if (flags & NFSEXP_ROOTSQUASH) {
  49                if (uid_eq(new->fsuid, GLOBAL_ROOT_UID))
  50                        new->fsuid = exp->ex_anon_uid;
  51                if (gid_eq(new->fsgid, GLOBAL_ROOT_GID))
  52                        new->fsgid = exp->ex_anon_gid;
  53
  54                gi = groups_alloc(rqgi->ngroups);
  55                if (!gi)
  56                        goto oom;
  57
  58                for (i = 0; i < rqgi->ngroups; i++) {
  59                        if (gid_eq(GLOBAL_ROOT_GID, rqgi->gid[i]))
  60                                gi->gid[i] = exp->ex_anon_gid;
  61                        else
  62                                gi->gid[i] = rqgi->gid[i];
  63                }
  64
  65                /* Each thread allocates its own gi, no race */
  66                groups_sort(gi);
  67        } else {
  68                gi = get_group_info(rqgi);
  69        }
  70
  71        if (uid_eq(new->fsuid, INVALID_UID))
  72                new->fsuid = exp->ex_anon_uid;
  73        if (gid_eq(new->fsgid, INVALID_GID))
  74                new->fsgid = exp->ex_anon_gid;
  75
  76        set_groups(new, gi);
  77        put_group_info(gi);
  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        abort_creds(new);
  92        return -ENOMEM;
  93}
  94
  95