diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 19:30:05 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 19:37:05 -0500 |
commit | 5c5fc09a1157a11dbe84e6421c3e0b37d05238cb (patch) | |
tree | 7a8e69867e323744d7431d50d73e479615f93595 | |
parent | 494f74a26c14d10bb26a45218b50feb75bdedeca (diff) |
NFS: Ensure we revalidate attributes before using execute_ok()
Donald Buczek reports that NFS clients can also report incorrect
results for access() due to lack of revalidation of attributes
before calling execute_ok().
Looking closely, it seems chdir() is afflicted with the same problem.
Fix is to ensure we call nfs_revalidate_inode_rcu() or
nfs_revalidate_inode() as appropriate before deciding to trust
execute_ok().
Reported-by: Donald Buczek <buczek@molgen.mpg.de>
Link: http://lkml.kernel.org/r/1451331530-3748-1-git-send-email-buczek@molgen.mpg.de
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/dir.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 44e519c21e18..5bd2f5bfaf57 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -2432,6 +2432,20 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | |||
2432 | } | 2432 | } |
2433 | EXPORT_SYMBOL_GPL(nfs_may_open); | 2433 | EXPORT_SYMBOL_GPL(nfs_may_open); |
2434 | 2434 | ||
2435 | static int nfs_execute_ok(struct inode *inode, int mask) | ||
2436 | { | ||
2437 | struct nfs_server *server = NFS_SERVER(inode); | ||
2438 | int ret; | ||
2439 | |||
2440 | if (mask & MAY_NOT_BLOCK) | ||
2441 | ret = nfs_revalidate_inode_rcu(server, inode); | ||
2442 | else | ||
2443 | ret = nfs_revalidate_inode(server, inode); | ||
2444 | if (ret == 0 && !execute_ok(inode)) | ||
2445 | ret = -EACCES; | ||
2446 | return ret; | ||
2447 | } | ||
2448 | |||
2435 | int nfs_permission(struct inode *inode, int mask) | 2449 | int nfs_permission(struct inode *inode, int mask) |
2436 | { | 2450 | { |
2437 | struct rpc_cred *cred; | 2451 | struct rpc_cred *cred; |
@@ -2484,8 +2498,8 @@ force_lookup: | |||
2484 | res = PTR_ERR(cred); | 2498 | res = PTR_ERR(cred); |
2485 | } | 2499 | } |
2486 | out: | 2500 | out: |
2487 | if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) | 2501 | if (!res && (mask & MAY_EXEC)) |
2488 | res = -EACCES; | 2502 | res = nfs_execute_ok(inode, mask); |
2489 | 2503 | ||
2490 | dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n", | 2504 | dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n", |
2491 | inode->i_sb->s_id, inode->i_ino, mask, res); | 2505 | inode->i_sb->s_id, inode->i_ino, mask, res); |