From 0ec757df9743025f14190d6034d8bd2bf37c2dd1 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 17 Jul 2007 04:04:48 -0700 Subject: [PATCH] knfsd: nfsd4: make readonly access depend on pseudoflavor 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" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsfh.c | 2 +- fs/nfsd/nfsproc.c | 3 ++- fs/nfsd/vfs.c | 13 +++++++------ include/linux/nfsd/export.h | 13 ++++++++++++- include/linux/nfsd/nfsd.h | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index d5fe392b14..8d2b499148 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -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, " diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index b2c7147aa9..977a71f64e 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -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) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8e109e586a..e90f4a8a1d 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -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; diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 424be41130..a01f775cb9 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -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); /* diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 62499c2f09..54ef1a18a5 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -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) -- 2.39.5