root/fs/nfsd/nfs2acl.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfsacld_proc_null
  2. nfsacld_proc_getacl
  3. nfsacld_proc_setacl
  4. nfsacld_proc_getattr
  5. nfsacld_proc_access
  6. nfsaclsvc_decode_getaclargs
  7. nfsaclsvc_decode_setaclargs
  8. nfsaclsvc_decode_fhandleargs
  9. nfsaclsvc_decode_accessargs
  10. nfsaclsvc_encode_voidres
  11. nfsaclsvc_encode_getaclres
  12. nfsaclsvc_encode_attrstatres
  13. nfsaclsvc_encode_accessres
  14. nfsaclsvc_release_getacl
  15. nfsaclsvc_release_attrstat
  16. nfsaclsvc_release_access

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Process version 2 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 NFSDDBG_FACILITY                NFSDDBG_PROC
  17 #define RETURN_STATUS(st)       { resp->status = (st); return (st); }
  18 
  19 /*
  20  * NULL call.
  21  */
  22 static __be32
  23 nfsacld_proc_null(struct svc_rqst *rqstp)
  24 {
  25         return nfs_ok;
  26 }
  27 
  28 /*
  29  * Get the Access and/or Default ACL of a file.
  30  */
  31 static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp)
  32 {
  33         struct nfsd3_getaclargs *argp = rqstp->rq_argp;
  34         struct nfsd3_getaclres *resp = rqstp->rq_resp;
  35         struct posix_acl *acl;
  36         struct inode *inode;
  37         svc_fh *fh;
  38         __be32 nfserr = 0;
  39 
  40         dprintk("nfsd: GETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
  41 
  42         fh = fh_copy(&resp->fh, &argp->fh);
  43         nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
  44         if (nfserr)
  45                 RETURN_STATUS(nfserr);
  46 
  47         inode = d_inode(fh->fh_dentry);
  48 
  49         if (argp->mask & ~NFS_ACL_MASK)
  50                 RETURN_STATUS(nfserr_inval);
  51         resp->mask = argp->mask;
  52 
  53         nfserr = fh_getattr(fh, &resp->stat);
  54         if (nfserr)
  55                 RETURN_STATUS(nfserr);
  56 
  57         if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
  58                 acl = get_acl(inode, ACL_TYPE_ACCESS);
  59                 if (acl == NULL) {
  60                         /* Solaris returns the inode's minimum ACL. */
  61                         acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
  62                 }
  63                 if (IS_ERR(acl)) {
  64                         nfserr = nfserrno(PTR_ERR(acl));
  65                         goto fail;
  66                 }
  67                 resp->acl_access = acl;
  68         }
  69         if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
  70                 /* Check how Solaris handles requests for the Default ACL
  71                    of a non-directory! */
  72                 acl = get_acl(inode, ACL_TYPE_DEFAULT);
  73                 if (IS_ERR(acl)) {
  74                         nfserr = nfserrno(PTR_ERR(acl));
  75                         goto fail;
  76                 }
  77                 resp->acl_default = acl;
  78         }
  79 
  80         /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
  81         RETURN_STATUS(0);
  82 
  83 fail:
  84         posix_acl_release(resp->acl_access);
  85         posix_acl_release(resp->acl_default);
  86         RETURN_STATUS(nfserr);
  87 }
  88 
  89 /*
  90  * Set the Access and/or Default ACL of a file.
  91  */
  92 static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
  93 {
  94         struct nfsd3_setaclargs *argp = rqstp->rq_argp;
  95         struct nfsd_attrstat *resp = rqstp->rq_resp;
  96         struct inode *inode;
  97         svc_fh *fh;
  98         __be32 nfserr = 0;
  99         int error;
 100 
 101         dprintk("nfsd: SETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
 102 
 103         fh = fh_copy(&resp->fh, &argp->fh);
 104         nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
 105         if (nfserr)
 106                 goto out;
 107 
 108         inode = d_inode(fh->fh_dentry);
 109 
 110         error = fh_want_write(fh);
 111         if (error)
 112                 goto out_errno;
 113 
 114         fh_lock(fh);
 115 
 116         error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
 117         if (error)
 118                 goto out_drop_lock;
 119         error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
 120         if (error)
 121                 goto out_drop_lock;
 122 
 123         fh_unlock(fh);
 124 
 125         fh_drop_write(fh);
 126 
 127         nfserr = fh_getattr(fh, &resp->stat);
 128 
 129 out:
 130         /* argp->acl_{access,default} may have been allocated in
 131            nfssvc_decode_setaclargs. */
 132         posix_acl_release(argp->acl_access);
 133         posix_acl_release(argp->acl_default);
 134         return nfserr;
 135 out_drop_lock:
 136         fh_unlock(fh);
 137         fh_drop_write(fh);
 138 out_errno:
 139         nfserr = nfserrno(error);
 140         goto out;
 141 }
 142 
 143 /*
 144  * Check file attributes
 145  */
 146 static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp)
 147 {
 148         struct nfsd_fhandle *argp = rqstp->rq_argp;
 149         struct nfsd_attrstat *resp = rqstp->rq_resp;
 150         __be32 nfserr;
 151         dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 152 
 153         fh_copy(&resp->fh, &argp->fh);
 154         nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
 155         if (nfserr)
 156                 return nfserr;
 157         nfserr = fh_getattr(&resp->fh, &resp->stat);
 158         return nfserr;
 159 }
 160 
 161 /*
 162  * Check file access
 163  */
 164 static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
 165 {
 166         struct nfsd3_accessargs *argp = rqstp->rq_argp;
 167         struct nfsd3_accessres *resp = rqstp->rq_resp;
 168         __be32 nfserr;
 169 
 170         dprintk("nfsd: ACCESS(2acl)   %s 0x%x\n",
 171                         SVCFH_fmt(&argp->fh),
 172                         argp->access);
 173 
 174         fh_copy(&resp->fh, &argp->fh);
 175         resp->access = argp->access;
 176         nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
 177         if (nfserr)
 178                 return nfserr;
 179         nfserr = fh_getattr(&resp->fh, &resp->stat);
 180         return nfserr;
 181 }
 182 
 183 /*
 184  * XDR decode functions
 185  */
 186 static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 187 {
 188         struct nfsd3_getaclargs *argp = rqstp->rq_argp;
 189 
 190         p = nfs2svc_decode_fh(p, &argp->fh);
 191         if (!p)
 192                 return 0;
 193         argp->mask = ntohl(*p); p++;
 194 
 195         return xdr_argsize_check(rqstp, p);
 196 }
 197 
 198 
 199 static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 200 {
 201         struct nfsd3_setaclargs *argp = rqstp->rq_argp;
 202         struct kvec *head = rqstp->rq_arg.head;
 203         unsigned int base;
 204         int n;
 205 
 206         p = nfs2svc_decode_fh(p, &argp->fh);
 207         if (!p)
 208                 return 0;
 209         argp->mask = ntohl(*p++);
 210         if (argp->mask & ~NFS_ACL_MASK ||
 211             !xdr_argsize_check(rqstp, p))
 212                 return 0;
 213 
 214         base = (char *)p - (char *)head->iov_base;
 215         n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
 216                           (argp->mask & NFS_ACL) ?
 217                           &argp->acl_access : NULL);
 218         if (n > 0)
 219                 n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
 220                                   (argp->mask & NFS_DFACL) ?
 221                                   &argp->acl_default : NULL);
 222         return (n > 0);
 223 }
 224 
 225 static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
 226 {
 227         struct nfsd_fhandle *argp = rqstp->rq_argp;
 228 
 229         p = nfs2svc_decode_fh(p, &argp->fh);
 230         if (!p)
 231                 return 0;
 232         return xdr_argsize_check(rqstp, p);
 233 }
 234 
 235 static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
 236 {
 237         struct nfsd3_accessargs *argp = rqstp->rq_argp;
 238 
 239         p = nfs2svc_decode_fh(p, &argp->fh);
 240         if (!p)
 241                 return 0;
 242         argp->access = ntohl(*p++);
 243 
 244         return xdr_argsize_check(rqstp, p);
 245 }
 246 
 247 /*
 248  * XDR encode functions
 249  */
 250 
 251 /*
 252  * There must be an encoding function for void results so svc_process
 253  * will work properly.
 254  */
 255 static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
 256 {
 257         return xdr_ressize_check(rqstp, p);
 258 }
 259 
 260 /* GETACL */
 261 static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
 262 {
 263         struct nfsd3_getaclres *resp = rqstp->rq_resp;
 264         struct dentry *dentry = resp->fh.fh_dentry;
 265         struct inode *inode;
 266         struct kvec *head = rqstp->rq_res.head;
 267         unsigned int base;
 268         int n;
 269         int w;
 270 
 271         /*
 272          * Since this is version 2, the check for nfserr in
 273          * nfsd_dispatch actually ensures the following cannot happen.
 274          * However, it seems fragile to depend on that.
 275          */
 276         if (dentry == NULL || d_really_is_negative(dentry))
 277                 return 0;
 278         inode = d_inode(dentry);
 279 
 280         p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 281         *p++ = htonl(resp->mask);
 282         if (!xdr_ressize_check(rqstp, p))
 283                 return 0;
 284         base = (char *)p - (char *)head->iov_base;
 285 
 286         rqstp->rq_res.page_len = w = nfsacl_size(
 287                 (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
 288                 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
 289         while (w > 0) {
 290                 if (!*(rqstp->rq_next_page++))
 291                         return 0;
 292                 w -= PAGE_SIZE;
 293         }
 294 
 295         n = nfsacl_encode(&rqstp->rq_res, base, inode,
 296                           resp->acl_access,
 297                           resp->mask & NFS_ACL, 0);
 298         if (n > 0)
 299                 n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
 300                                   resp->acl_default,
 301                                   resp->mask & NFS_DFACL,
 302                                   NFS_ACL_DEFAULT);
 303         return (n > 0);
 304 }
 305 
 306 static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
 307 {
 308         struct nfsd_attrstat *resp = rqstp->rq_resp;
 309 
 310         p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 311         return xdr_ressize_check(rqstp, p);
 312 }
 313 
 314 /* ACCESS */
 315 static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
 316 {
 317         struct nfsd3_accessres *resp = rqstp->rq_resp;
 318 
 319         p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 320         *p++ = htonl(resp->access);
 321         return xdr_ressize_check(rqstp, p);
 322 }
 323 
 324 /*
 325  * XDR release functions
 326  */
 327 static void nfsaclsvc_release_getacl(struct svc_rqst *rqstp)
 328 {
 329         struct nfsd3_getaclres *resp = rqstp->rq_resp;
 330 
 331         fh_put(&resp->fh);
 332         posix_acl_release(resp->acl_access);
 333         posix_acl_release(resp->acl_default);
 334 }
 335 
 336 static void nfsaclsvc_release_attrstat(struct svc_rqst *rqstp)
 337 {
 338         struct nfsd_attrstat *resp = rqstp->rq_resp;
 339 
 340         fh_put(&resp->fh);
 341 }
 342 
 343 static void nfsaclsvc_release_access(struct svc_rqst *rqstp)
 344 {
 345         struct nfsd3_accessres *resp = rqstp->rq_resp;
 346 
 347         fh_put(&resp->fh);
 348 }
 349 
 350 #define nfsaclsvc_decode_voidargs       NULL
 351 #define nfsaclsvc_release_void          NULL
 352 #define nfsd3_fhandleargs       nfsd_fhandle
 353 #define nfsd3_attrstatres       nfsd_attrstat
 354 #define nfsd3_voidres           nfsd3_voidargs
 355 struct nfsd3_voidargs { int dummy; };
 356 
 357 #define PROC(name, argt, rest, relt, cache, respsize)                   \
 358 {                                                                       \
 359         .pc_func        = nfsacld_proc_##name,                          \
 360         .pc_decode      = nfsaclsvc_decode_##argt##args,                \
 361         .pc_encode      = nfsaclsvc_encode_##rest##res,                 \
 362         .pc_release     = nfsaclsvc_release_##relt,     \
 363         .pc_argsize     = sizeof(struct nfsd3_##argt##args),            \
 364         .pc_ressize     = sizeof(struct nfsd3_##rest##res),             \
 365         .pc_cachetype   = cache,                                        \
 366         .pc_xdrressize  = respsize,                                     \
 367 }
 368 
 369 #define ST 1            /* status*/
 370 #define AT 21           /* attributes */
 371 #define pAT (1+AT)      /* post attributes - conditional */
 372 #define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
 373 
 374 static const struct svc_procedure nfsd_acl_procedures2[] = {
 375   PROC(null,    void,           void,           void,     RC_NOCACHE, ST),
 376   PROC(getacl,  getacl,         getacl,         getacl,   RC_NOCACHE, ST+1+2*(1+ACL)),
 377   PROC(setacl,  setacl,         attrstat,       attrstat, RC_NOCACHE, ST+AT),
 378   PROC(getattr, fhandle,        attrstat,       attrstat, RC_NOCACHE, ST+AT),
 379   PROC(access,  access,         access,         access,   RC_NOCACHE, ST+AT+1),
 380 };
 381 
 382 static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
 383 const struct svc_version nfsd_acl_version2 = {
 384         .vs_vers        = 2,
 385         .vs_nproc       = 5,
 386         .vs_proc        = nfsd_acl_procedures2,
 387         .vs_count       = nfsd_acl_count2,
 388         .vs_dispatch    = nfsd_dispatch,
 389         .vs_xdrsize     = NFS3_SVC_XDRSIZE,
 390 };

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