Commit 591249aa authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] Fix nfsd checking for read-only filesystem.

Currently nfsd only worries about read-only exports for
directories and files, which allows device special files
to be chmodded (for example).

This patch extends the test to cover all files, but is careful
to avoid it when an IRIX client is doing an write-permission test
against a pre-existing device special file.
parent b58b7c71
...@@ -250,11 +250,11 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, ...@@ -250,11 +250,11 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
/* this is probably a permission check.. /* this is probably a permission check..
* at least IRIX implements perm checking on * at least IRIX implements perm checking on
* echo thing > device-special-file-or-pipe * echo thing > device-special-file-or-pipe
* by does a CREATE with type==0 * by doing a CREATE with type==0
*/ */
nfserr = nfsd_permission(newfhp->fh_export, nfserr = nfsd_permission(newfhp->fh_export,
newfhp->fh_dentry, newfhp->fh_dentry,
MAY_WRITE); MAY_WRITE|MAY_LOCAL_ACCESS);
if (nfserr && nfserr != nfserr_rofs) if (nfserr && nfserr != nfserr_rofs)
goto out_unlock; goto out_unlock;
} }
......
...@@ -1515,11 +1515,11 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) ...@@ -1515,11 +1515,11 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
#endif #endif
/* only care about readonly exports for files and /* Normally we reject any write/sattr etc access on a read-only file
* directories. links don't have meaningful write access, * system. But if it is IRIX doing check on write-access for a
* and all else is local to the client * device special file, we ignore rofs.
*/ */
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) if (!(acc & MAY_LOCAL_ACCESS))
if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
if (EX_RDONLY(exp) || IS_RDONLY(inode)) if (EX_RDONLY(exp) || IS_RDONLY(inode))
return nfserr_rofs; return nfserr_rofs;
......
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define MAY_TRUNC 16 #define MAY_TRUNC 16
#define MAY_LOCK 32 #define MAY_LOCK 32
#define MAY_OWNER_OVERRIDE 64 #define MAY_OWNER_OVERRIDE 64
#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAX_OWNER_OVERRIDE) & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_OWNER_OVERRIDE) #define MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAX_OWNER_OVERRIDE | MAY_LOCAL_ACCESS) & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_OWNER_OVERRIDE)
# error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_OWNER_OVERRIDE." # error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_OWNER_OVERRIDE."
#endif #endif
#define MAY_CREATE (MAY_EXEC|MAY_WRITE) #define MAY_CREATE (MAY_EXEC|MAY_WRITE)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment