knfsd: nfsd4: make readonly access depend on pseudoflavor
authorJ. Bruce Fields <bfields@citi.umich.edu>
Tue, 17 Jul 2007 11:04:48 +0000 (04:04 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 17 Jul 2007 17:23:08 +0000 (10:23 -0700)
Allow readonly access to vary depending on the pseudoflavor, using the flag
passed with each pseudoflavor in the export downcall.  The rest of the flags
are ignored for now, though some day we might also allow id squashing to vary
based on the flavor.

Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/vfs.c
include/linux/nfsd/export.h
include/linux/nfsd/nfsd.h

index d5fe392b14fb0767ffb352f82e1c48cfbf5ac823..8d2b49914843c91957b9c5b6cf1dad3b5ecb6b9e 100644 (file)
@@ -255,7 +255,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                goto out;
 
        /* Finally, check access permissions. */
-       error = nfsd_permission(exp, dentry, access);
+       error = nfsd_permission(rqstp, exp, dentry, access);
 
        if (error) {
                dprintk("fh_verify: %s/%s permission failure, "
index b2c7147aa921414c9243012a513861dbea3c8133..977a71f64e190697291ab598a517ee8a290ee425 100644 (file)
@@ -278,7 +278,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
                                         *   echo thing > device-special-file-or-pipe
                                         * by doing a CREATE with type==0
                                         */
-                                       nfserr = nfsd_permission(newfhp->fh_export,
+                                       nfserr = nfsd_permission(rqstp,
+                                                                newfhp->fh_export,
                                                                 newfhp->fh_dentry,
                                                                 MAY_WRITE|MAY_LOCAL_ACCESS);
                                        if (nfserr && nfserr != nfserr_rofs)
index 8e109e586a74c7b706ffcdd812ad28c216c9d738..e90f4a8a1d011f11898834ae7984ef2a3cb9b92e 100644 (file)
@@ -328,7 +328,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        /* The size case is special. It changes the file as well as the attributes.  */
        if (iap->ia_valid & ATTR_SIZE) {
                if (iap->ia_size < inode->i_size) {
-                       err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
+                       err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
                        if (err)
                                goto out;
                }
@@ -616,7 +616,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
 
                        sresult |= map->access;
 
-                       err2 = nfsd_permission(export, dentry, map->how);
+                       err2 = nfsd_permission(rqstp, export, dentry, map->how);
                        switch (err2) {
                        case nfs_ok:
                                result |= map->access;
@@ -1043,7 +1043,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        __be32          err;
 
        if (file) {
-               err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+               err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
                                MAY_READ|MAY_OWNER_OVERRIDE);
                if (err)
                        goto out;
@@ -1072,7 +1072,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        __be32                  err = 0;
 
        if (file) {
-               err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+               err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
                                MAY_WRITE|MAY_OWNER_OVERRIDE);
                if (err)
                        goto out;
@@ -1801,7 +1801,8 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
  * Check for a user's access permissions to this inode.
  */
 __be32
-nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
+nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+                                       struct dentry *dentry, int acc)
 {
        struct inode    *inode = dentry->d_inode;
        int             err;
@@ -1832,7 +1833,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
         */
        if (!(acc & MAY_LOCAL_ACCESS))
                if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
-                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
+                       if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
                                return nfserr_rofs;
                        if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
                                return nfserr_perm;
index 424be41130ba3630c7a1ed810888754c6d66003b..a01f775cb9445fb9214c3aab87a4c5080b5c27b8 100644 (file)
@@ -112,10 +112,21 @@ struct svc_expkey {
 
 #define EX_SECURE(exp)         (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)         (!((exp)->ex_flags & NFSEXP_ASYNC))
-#define EX_RDONLY(exp)         ((exp)->ex_flags & NFSEXP_READONLY)
 #define EX_NOHIDE(exp)         ((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_WGATHER(exp)                ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
+static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+       struct exp_flavor_info *f;
+       struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+       for (f = exp->ex_flavors; f < end; f++) {
+               if (f->pseudoflavor == rqstp->rq_flavor)
+                       return f->flags & NFSEXP_READONLY;
+       }
+       return exp->ex_flags & NFSEXP_READONLY;
+}
+
 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
 
 /*
index 62499c2f09185be6d66c30d034a62cf68b6537d7..54ef1a18a56c1674807b0cc631a8c4278fab4a4d 100644 (file)
@@ -119,7 +119,8 @@ __be32              nfsd_statfs(struct svc_rqst *, struct svc_fh *,
                                struct kstatfs *);
 
 int            nfsd_notify_change(struct inode *, struct iattr *);
-__be32         nfsd_permission(struct svc_export *, struct dentry *, int);
+__be32         nfsd_permission(struct svc_rqst *, struct svc_export *,
+                               struct dentry *, int);
 int            nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)