Commit ecbb903c authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFS: Be more careful about mapping file permissions

When mapping a directory, we want the MAY_WRITE permissions to reflect
whether or not we have permission to modify, add and delete the directory
entries. MAY_EXEC must map to lookup permissions.

On the other hand, for files, we want MAY_WRITE to reflect a permission
to modify and extend the file.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent bd8b2441
...@@ -2379,21 +2379,30 @@ EXPORT_SYMBOL_GPL(nfs_access_add_cache); ...@@ -2379,21 +2379,30 @@ EXPORT_SYMBOL_GPL(nfs_access_add_cache);
#define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \ #define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \
NFS4_ACCESS_EXTEND | \ NFS4_ACCESS_EXTEND | \
NFS4_ACCESS_DELETE) NFS4_ACCESS_DELETE)
#define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \
NFS4_ACCESS_EXTEND)
#define NFS_DIR_MAY_WRITE NFS_MAY_WRITE
#define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP) #define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP)
#define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE) #define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE)
static int static int
nfs_access_calc_mask(u32 access_result) nfs_access_calc_mask(u32 access_result, umode_t umode)
{ {
int mask = 0; int mask = 0;
if (access_result & NFS_MAY_READ) if (access_result & NFS_MAY_READ)
mask |= MAY_READ; mask |= MAY_READ;
if (access_result & NFS_MAY_WRITE) if (S_ISDIR(umode)) {
mask |= MAY_WRITE; if ((access_result & NFS_DIR_MAY_WRITE) == NFS_DIR_MAY_WRITE)
if (access_result & NFS_MAY_LOOKUP) mask |= MAY_WRITE;
mask |= MAY_EXEC; if ((access_result & NFS_MAY_LOOKUP) == NFS_MAY_LOOKUP)
if (access_result & NFS_MAY_EXECUTE) mask |= MAY_EXEC;
mask |= MAY_EXEC; } else if (S_ISREG(umode)) {
if ((access_result & NFS_FILE_MAY_WRITE) == NFS_FILE_MAY_WRITE)
mask |= MAY_WRITE;
if ((access_result & NFS_MAY_EXECUTE) == NFS_MAY_EXECUTE)
mask |= MAY_EXEC;
} else if (access_result & NFS_MAY_WRITE)
mask |= MAY_WRITE;
return mask; return mask;
} }
...@@ -2438,7 +2447,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) ...@@ -2438,7 +2447,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
} }
nfs_access_add_cache(inode, &cache); nfs_access_add_cache(inode, &cache);
out_cached: out_cached:
cache_mask = nfs_access_calc_mask(cache.mask); cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
status = -EACCES; status = -EACCES;
out: out:
......
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