aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2007-07-17 07:04:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:08 -0400
commit0ec757df9743025f14190d6034d8bd2bf37c2dd1 (patch)
tree77436cbdc8c241aceab2daed243606e17e126771
parent32c1eb0cd7ee00b5eb7b6f7059c635fbc1052966 (diff)
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" <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>
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfsproc.c3
-rw-r--r--fs/nfsd/vfs.c13
-rw-r--r--include/linux/nfsd/export.h13
-rw-r--r--include/linux/nfsd/nfsd.h3
5 files changed, 24 insertions, 10 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index d5fe392b14fb..8d2b49914843 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)
255 goto out; 255 goto out;
256 256
257 /* Finally, check access permissions. */ 257 /* Finally, check access permissions. */
258 error = nfsd_permission(exp, dentry, access); 258 error = nfsd_permission(rqstp, exp, dentry, access);
259 259
260 if (error) { 260 if (error) {
261 dprintk("fh_verify: %s/%s permission failure, " 261 dprintk("fh_verify: %s/%s permission failure, "
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index b2c7147aa921..977a71f64e19 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,
278 * echo thing > device-special-file-or-pipe 278 * echo thing > device-special-file-or-pipe
279 * by doing a CREATE with type==0 279 * by doing a CREATE with type==0
280 */ 280 */
281 nfserr = nfsd_permission(newfhp->fh_export, 281 nfserr = nfsd_permission(rqstp,
282 newfhp->fh_export,
282 newfhp->fh_dentry, 283 newfhp->fh_dentry,
283 MAY_WRITE|MAY_LOCAL_ACCESS); 284 MAY_WRITE|MAY_LOCAL_ACCESS);
284 if (nfserr && nfserr != nfserr_rofs) 285 if (nfserr && nfserr != nfserr_rofs)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8e109e586a74..e90f4a8a1d01 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,
328 /* The size case is special. It changes the file as well as the attributes. */ 328 /* The size case is special. It changes the file as well as the attributes. */
329 if (iap->ia_valid & ATTR_SIZE) { 329 if (iap->ia_valid & ATTR_SIZE) {
330 if (iap->ia_size < inode->i_size) { 330 if (iap->ia_size < inode->i_size) {
331 err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); 331 err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
332 if (err) 332 if (err)
333 goto out; 333 goto out;
334 } 334 }
@@ -616,7 +616,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
616 616
617 sresult |= map->access; 617 sresult |= map->access;
618 618
619 err2 = nfsd_permission(export, dentry, map->how); 619 err2 = nfsd_permission(rqstp, export, dentry, map->how);
620 switch (err2) { 620 switch (err2) {
621 case nfs_ok: 621 case nfs_ok:
622 result |= map->access; 622 result |= map->access;
@@ -1043,7 +1043,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1043 __be32 err; 1043 __be32 err;
1044 1044
1045 if (file) { 1045 if (file) {
1046 err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, 1046 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
1047 MAY_READ|MAY_OWNER_OVERRIDE); 1047 MAY_READ|MAY_OWNER_OVERRIDE);
1048 if (err) 1048 if (err)
1049 goto out; 1049 goto out;
@@ -1072,7 +1072,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1072 __be32 err = 0; 1072 __be32 err = 0;
1073 1073
1074 if (file) { 1074 if (file) {
1075 err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, 1075 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
1076 MAY_WRITE|MAY_OWNER_OVERRIDE); 1076 MAY_WRITE|MAY_OWNER_OVERRIDE);
1077 if (err) 1077 if (err)
1078 goto out; 1078 goto out;
@@ -1801,7 +1801,8 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
1801 * Check for a user's access permissions to this inode. 1801 * Check for a user's access permissions to this inode.
1802 */ 1802 */
1803__be32 1803__be32
1804nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) 1804nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
1805 struct dentry *dentry, int acc)
1805{ 1806{
1806 struct inode *inode = dentry->d_inode; 1807 struct inode *inode = dentry->d_inode;
1807 int err; 1808 int err;
@@ -1832,7 +1833,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
1832 */ 1833 */
1833 if (!(acc & MAY_LOCAL_ACCESS)) 1834 if (!(acc & MAY_LOCAL_ACCESS))
1834 if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { 1835 if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
1835 if (EX_RDONLY(exp) || IS_RDONLY(inode)) 1836 if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
1836 return nfserr_rofs; 1837 return nfserr_rofs;
1837 if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) 1838 if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
1838 return nfserr_perm; 1839 return nfserr_perm;
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 424be41130ba..a01f775cb944 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -112,10 +112,21 @@ struct svc_expkey {
112 112
113#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) 113#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
114#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) 114#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
115#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY)
116#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) 115#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
117#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) 116#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
118 117
118static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
119{
120 struct exp_flavor_info *f;
121 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
122
123 for (f = exp->ex_flavors; f < end; f++) {
124 if (f->pseudoflavor == rqstp->rq_flavor)
125 return f->flags & NFSEXP_READONLY;
126 }
127 return exp->ex_flags & NFSEXP_READONLY;
128}
129
119__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp); 130__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
120 131
121/* 132/*
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 62499c2f0918..54ef1a18a56c 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 *,
119 struct kstatfs *); 119 struct kstatfs *);
120 120
121int nfsd_notify_change(struct inode *, struct iattr *); 121int nfsd_notify_change(struct inode *, struct iattr *);
122__be32 nfsd_permission(struct svc_export *, struct dentry *, int); 122__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
123 struct dentry *, int);
123int nfsd_sync_dir(struct dentry *dp); 124int nfsd_sync_dir(struct dentry *dp);
124 125
125#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 126#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)