root/fs/nfsd/nfs3acl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfsd3_proc_null
  2. nfsd3_proc_getacl
  3. nfsd3_proc_setacl
  4. nfs3svc_decode_getaclargs
  5. nfs3svc_decode_setaclargs
  6. nfs3svc_encode_getaclres
  7. nfs3svc_encode_setaclres
  8. nfs3svc_release_getacl

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Process version 3 NFSACL requests.
   4  *
   5  * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
   6  */
   7 
   8 #include "nfsd.h"
   9 /* FIXME: nfsacl.h is a broken header */
  10 #include <linux/nfsacl.h>
  11 #include <linux/gfp.h>
  12 #include "cache.h"
  13 #include "xdr3.h"
  14 #include "vfs.h"
  15 
  16 #define RETURN_STATUS(st)       { resp->status = (st); return (st); }
  17 
  18 /*
  19  * NULL call.
  20  */
  21 static __be32
  22 nfsd3_proc_null(struct svc_rqst *rqstp)
  23 {
  24         return nfs_ok;
  25 }
  26 
  27 /*
  28  * Get the Access and/or Default ACL of a file.
  29  */
  30 static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp)
  31 {
  32         struct nfsd3_getaclargs *argp = rqstp->rq_argp;
  33         struct nfsd3_getaclres *resp = rqstp->rq_resp;
  34         struct posix_acl *acl;
  35         struct inode *inode;
  36         svc_fh *fh;
  37         __be32 nfserr = 0;
  38 
  39         fh = fh_copy(&resp->fh, &argp->fh);
  40         nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
  41         if (nfserr)
  42                 RETURN_STATUS(nfserr);
  43 
  44         inode = d_inode(fh->fh_dentry);
  45 
  46         if (argp->mask & ~NFS_ACL_MASK)
  47                 RETURN_STATUS(nfserr_inval);
  48         resp->mask = argp->mask;
  49 
  50         if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
  51                 acl = get_acl(inode, ACL_TYPE_ACCESS);
  52                 if (acl == NULL) {
  53                         /* Solaris returns the inode's minimum ACL. */
  54                         acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
  55                 }
  56                 if (IS_ERR(acl)) {
  57                         nfserr = nfserrno(PTR_ERR(acl));
  58                         goto fail;
  59                 }
  60                 resp->acl_access = acl;
  61         }
  62         if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
  63                 /* Check how Solaris handles requests for the Default ACL
  64                    of a non-directory! */
  65                 acl = get_acl(inode, ACL_TYPE_DEFAULT);
  66                 if (IS_ERR(acl)) {
  67                         nfserr = nfserrno(PTR_ERR(acl));
  68                         goto fail;
  69                 }
  70                 resp->acl_default = acl;
  71         }
  72 
  73         /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
  74         RETURN_STATUS(0);
  75 
  76 fail:
  77         posix_acl_release(resp->acl_access);
  78         posix_acl_release(resp->acl_default);
  79         RETURN_STATUS(nfserr);
  80 }
  81 
  82 /*
  83  * Set the Access and/or Default ACL of a file.
  84  */
  85 static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
  86 {
  87         struct nfsd3_setaclargs *argp = rqstp->rq_argp;
  88         struct nfsd3_attrstat *resp = rqstp->rq_resp;
  89         struct inode *inode;
  90         svc_fh *fh;
  91         __be32 nfserr = 0;
  92         int error;
  93 
  94         fh = fh_copy(&resp->fh, &argp->fh);
  95         nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
  96         if (nfserr)
  97                 goto out;
  98 
  99         inode = d_inode(fh->fh_dentry);
 100 
 101         error = fh_want_write(fh);
 102         if (error)
 103                 goto out_errno;
 104 
 105         fh_lock(fh);
 106 
 107         error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
 108         if (error)
 109                 goto out_drop_lock;
 110         error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
 111 
 112 out_drop_lock:
 113         fh_unlock(fh);
 114         fh_drop_write(fh);
 115 out_errno:
 116         nfserr = nfserrno(error);
 117 out:
 118         /* argp->acl_{access,default} may have been allocated in
 119            nfs3svc_decode_setaclargs. */
 120         posix_acl_release(argp->acl_access);
 121         posix_acl_release(argp->acl_default);
 122         RETURN_STATUS(nfserr);
 123 }
 124 
 125 /*
 126  * XDR decode functions
 127  */
 128 static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 129 {
 130         struct nfsd3_getaclargs *args = rqstp->rq_argp;
 131 
 132         p = nfs3svc_decode_fh(p, &args->fh);
 133         if (!p)
 134                 return 0;
 135         args->mask = ntohl(*p); p++;
 136 
 137         return xdr_argsize_check(rqstp, p);
 138 }
 139 
 140 
 141 static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 142 {
 143         struct nfsd3_setaclargs *args = rqstp->rq_argp;
 144         struct kvec *head = rqstp->rq_arg.head;
 145         unsigned int base;
 146         int n;
 147 
 148         p = nfs3svc_decode_fh(p, &args->fh);
 149         if (!p)
 150                 return 0;
 151         args->mask = ntohl(*p++);
 152         if (args->mask & ~NFS_ACL_MASK ||
 153             !xdr_argsize_check(rqstp, p))
 154                 return 0;
 155 
 156         base = (char *)p - (char *)head->iov_base;
 157         n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
 158                           (args->mask & NFS_ACL) ?
 159                           &args->acl_access : NULL);
 160         if (n > 0)
 161                 n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
 162                                   (args->mask & NFS_DFACL) ?
 163                                   &args->acl_default : NULL);
 164         return (n > 0);
 165 }
 166 
 167 /*
 168  * XDR encode functions
 169  */
 170 
 171 /* GETACL */
 172 static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
 173 {
 174         struct nfsd3_getaclres *resp = rqstp->rq_resp;
 175         struct dentry *dentry = resp->fh.fh_dentry;
 176 
 177         p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
 178         if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
 179                 struct inode *inode = d_inode(dentry);
 180                 struct kvec *head = rqstp->rq_res.head;
 181                 unsigned int base;
 182                 int n;
 183                 int w;
 184 
 185                 *p++ = htonl(resp->mask);
 186                 if (!xdr_ressize_check(rqstp, p))
 187                         return 0;
 188                 base = (char *)p - (char *)head->iov_base;
 189 
 190                 rqstp->rq_res.page_len = w = nfsacl_size(
 191                         (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
 192                         (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
 193                 while (w > 0) {
 194                         if (!*(rqstp->rq_next_page++))
 195                                 return 0;
 196                         w -= PAGE_SIZE;
 197                 }
 198 
 199                 n = nfsacl_encode(&rqstp->rq_res, base, inode,
 200                                   resp->acl_access,
 201                                   resp->mask & NFS_ACL, 0);
 202                 if (n > 0)
 203                         n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
 204                                           resp->acl_default,
 205                                           resp->mask & NFS_DFACL,
 206                                           NFS_ACL_DEFAULT);
 207                 if (n <= 0)
 208                         return 0;
 209         } else
 210                 if (!xdr_ressize_check(rqstp, p))
 211                         return 0;
 212 
 213         return 1;
 214 }
 215 
 216 /* SETACL */
 217 static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p)
 218 {
 219         struct nfsd3_attrstat *resp = rqstp->rq_resp;
 220 
 221         p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
 222 
 223         return xdr_ressize_check(rqstp, p);
 224 }
 225 
 226 /*
 227  * XDR release functions
 228  */
 229 static void nfs3svc_release_getacl(struct svc_rqst *rqstp)
 230 {
 231         struct nfsd3_getaclres *resp = rqstp->rq_resp;
 232 
 233         fh_put(&resp->fh);
 234         posix_acl_release(resp->acl_access);
 235         posix_acl_release(resp->acl_default);
 236 }
 237 
 238 #define nfs3svc_decode_voidargs         NULL
 239 #define nfs3svc_release_void            NULL
 240 #define nfsd3_setaclres                 nfsd3_attrstat
 241 #define nfsd3_voidres                   nfsd3_voidargs
 242 struct nfsd3_voidargs { int dummy; };
 243 
 244 #define PROC(name, argt, rest, relt, cache, respsize)                   \
 245 {                                                                       \
 246         .pc_func        = nfsd3_proc_##name,                            \
 247         .pc_decode      = nfs3svc_decode_##argt##args,                  \
 248         .pc_encode      = nfs3svc_encode_##rest##res,                   \
 249         .pc_release     = nfs3svc_release_##relt,                       \
 250         .pc_argsize     = sizeof(struct nfsd3_##argt##args),            \
 251         .pc_ressize     = sizeof(struct nfsd3_##rest##res),             \
 252         .pc_cachetype   = cache,                                        \
 253         .pc_xdrressize  = respsize,                                     \
 254 }
 255 
 256 #define ST 1            /* status*/
 257 #define AT 21           /* attributes */
 258 #define pAT (1+AT)      /* post attributes - conditional */
 259 #define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
 260 
 261 static const struct svc_procedure nfsd_acl_procedures3[] = {
 262   PROC(null,    void,           void,           void,     RC_NOCACHE, ST),
 263   PROC(getacl,  getacl,         getacl,         getacl,   RC_NOCACHE, ST+1+2*(1+ACL)),
 264   PROC(setacl,  setacl,         setacl,         fhandle,  RC_NOCACHE, ST+pAT),
 265 };
 266 
 267 static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];
 268 const struct svc_version nfsd_acl_version3 = {
 269         .vs_vers        = 3,
 270         .vs_nproc       = 3,
 271         .vs_proc        = nfsd_acl_procedures3,
 272         .vs_count       = nfsd_acl_count3,
 273         .vs_dispatch    = nfsd_dispatch,
 274         .vs_xdrsize     = NFS3_SVC_XDRSIZE,
 275 };
 276 

/* [<][>][^][v][top][bottom][index][help] */