Bug 109771

Summary: NFSv4 cached attributes never expire when challenged via exec() family instead of stat()
Product: File System Reporter: Donald Buczek (buczek)
Component: NFSAssignee: Trond Myklebust (trondmy)
Status: NEW ---    
Severity: normal CC: szg00000
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 4.3.3 ( 3.10.20 , 3.14.54 , 4.0.5 ) Subsystem:
Regression: No Bisected commit-id:
Attachments: demonstrate problem with cached attributes
suggested patch

Description Donald Buczek 2015-12-22 09:12:08 UTC
Created attachment 197991 [details]
demonstrate problem with cached attributes

The attached test.sh script demonstrates the problem.

real-life Situation: 
A file (script) is created without execute permission on a exported filesystem. Next the script is accessed by a NFSv4 client (in our case a cluster node trying to execute it, which correctly fails). Next the modes of the script are fixed ("chmod +x") on the server (or on another nfs client) by the user.

However, when execution is retried on the nfs client, it will continue to fail even after waiting multiple times longer than any nfs cache timeouts.

This is nfsv4 specific.

Results (of the attached test.sh script) :

nfs mount option=""
version             wait            status
----------------------------------------------
3.14.54             300             FAIL(#1)
3.10.29             300             FAIL(#1)
4.0.5               300             FAIL(#1)
4.3.3               300             FAIL(#1)  

version=3.14.54
option              wait            status
----------------------------------------------
""                  40              FAIL(#1)
nfsvers=3           40              OK
noac                40              FAIL(#2)
noac                300             FAIL(#2)
actimeo=5           40              FAIL(#1) 

#1 : ./test.sh: line 31: /tmp/nfs_mnt/test.sh: Permission denied
#2 : ./test.sh: /tmp/nfs_mnt/test.sh: /bin/sh: bad interpreter: Permission denied
Comment 1 Donald Buczek 2015-12-23 14:25:59 UTC
The problem is in fs/nfs/dir.c nfs_permission()  ( http://lxr.free-electrons.com/source/fs/nfs/dir.c#L2438 )

The call in line 2473 queries the server via _nfs4_proc_access for MAY_READ and MAY_ACCESS. The server response is used to update the "access" parameter in the cache, but not the "mode" parameter or the mode in the inode.

In line 2487 is an additional check, where execute_ok(inode) uses inode->i_mode, which is never updated. The -EACCESS here is the one preventing the script from being executed.

With nfs3 the problem doesn't manifest, because the LOOKUP used to find the script will get all attributes right away, so the cache is fresh.

My test script executes well, when the check in 2487,2488 is removed.

This check was refactored by https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=f696a3659fc4b3a3bf4bc83d9dbec5e5a2ffd929 from namei.c into the individual permission functions of the filesystems.

Do we need the check for nfs (where the access check has been done by the server and the mode might be misleading due to uid translation etc. anyway) ?
Comment 2 Donald Buczek 2015-12-25 12:22:32 UTC
Created attachment 198231 [details]
suggested patch
Comment 3 Donald Buczek 2016-01-27 07:26:37 UTC
Fixed by

  NFS: Fix attribute cache revalidation
  NFS: Ensure we revalidate attributes before using execute_ok()
  NFSv4: Don't perform cached access checks before we've OPENed the file

in v4.5-rc1