Skip to content

Commit

Permalink
knfsd: nfsd4: make readonly access depend on pseudoflavor
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
J. Bruce Fields authored and Linus Torvalds committed Jul 17, 2007
1 parent 32c1eb0 commit 0ec757d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 10 deletions.
2 changes: 1 addition & 1 deletion fs/nfsd/nfsfh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, "
Expand Down
3 changes: 2 additions & 1 deletion fs/nfsd/nfsproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 7 additions & 6 deletions fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 12 additions & 1 deletion include/linux/nfsd/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand Down
3 changes: 2 additions & 1 deletion include/linux/nfsd/nfsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 0ec757d

Please sign in to comment.