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>
goto out;
/* Finally, check access permissions. */
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, "
if (error) {
dprintk("fh_verify: %s/%s permission failure, "
* echo thing > device-special-file-or-pipe
* by doing a CREATE with type==0
*/
* 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)
newfhp->fh_dentry,
MAY_WRITE|MAY_LOCAL_ACCESS);
if (nfserr && nfserr != nfserr_rofs)
/* 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) {
/* 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);
- err2 = nfsd_permission(export, dentry, map->how);
+ err2 = nfsd_permission(rqstp, export, dentry, map->how);
switch (err2) {
case nfs_ok:
result |= map->access;
switch (err2) {
case nfs_ok:
result |= map->access;
- 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;
MAY_READ|MAY_OWNER_OVERRIDE);
if (err)
goto out;
__be32 err = 0;
if (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;
MAY_WRITE|MAY_OWNER_OVERRIDE);
if (err)
goto out;
* Check for a user's access permissions to this inode.
*/
__be32
* 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;
{
struct inode *inode = dentry->d_inode;
int err;
*/
if (!(acc & MAY_LOCAL_ACCESS))
if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
*/
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;
return nfserr_rofs;
if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
return nfserr_perm;
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
#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)
#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);
/*
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
/*
struct kstatfs *);
int nfsd_notify_change(struct inode *, struct iattr *);
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)
int nfsd_sync_dir(struct dentry *dp);
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)