Hi,
I noticed the following behavior on OpenAFS on Linux (1.4.12+dfsg-3 on
Ubuntu 10.04 i386, but I've seen symptoms explainable by this behavior on
other Linux systems). Given that /mit/geofft/hello.c is in AFS and
system:anyuser l (not rl) and geofft rlidkwa, and I have tokens for geofft
but root does not:
geo...@white-elephant:/tmp$ cat access.c
#include <unistd.h>
main() {
perror("access", access("/mit/geofft/hello.c", F_OK));
return 0;
}
geo...@white-elephant:/tmp$ ./access
access: Success
geo...@white-elephant:/tmp$ sudo ./access
access: Success
geo...@white-elephant:/tmp$ fs flushv /mit/geofft/
geo...@white-elephant:/tmp$ sudo ./access
access: Permission denied
geo...@white-elephant:/tmp$ sudo stat /mit/geofft/hello.c
stat: cannot stat `/mit/geofft/hello.c': Permission denied
geo...@white-elephant:/tmp$ ./access
access: Success
geo...@white-elephant:/tmp$ sudo ./access
access: Success
geo...@white-elephant:/tmp$ sudo stat /mit/geofft/hello.c
File: `/mit/geofft/hello.c'
Size: 148 Blocks: 2 IO Block: 4096 regular file
Device: 16h/22d Inode: 1101648276 Links: 1
Access: (0600/-rw-------) Uid: (40490/ UNKNOWN) Gid: ( 101/ libuuid)
Access: 2008-09-09 06:40:03.000000000 -0400
Modify: 2008-09-09 06:40:03.000000000 -0400
Change: 2008-09-09 06:40:03.000000000 -0400
In other words, access(F_OK) or stat() on a file that clearly exists
returns EACCES until such time as a user who has more permissions tries to
access it. At that point, access(F_OK) will return 0 and stat() will
return stat info until it leaves cache. (Note that for nonexistent files
it will correctly return ENOENT instead.)
It's not really clear to me that POSIX permits access(F_OK) to return
EACCES if all the directories up to that point are searchable (i.e., "l"),
and either way the cache-dependent behavior of 0 vs. EACCES is confusing.
øFor example, the current implementation of Kerberos' .k5login-checking
behavior effectively assumes that any nonzero return of access(F_OK) must
be ENOENT, so if you have a non-world-readable .k5login file, it will
_mostly_ appear to krb5_kuserok to not exist by access() returning EACCES,
but if you get your .k5login into cache, access() will start returning 0
instead, and you'll be unable to log in for some period of time (since the
file isn't world-readable). We've suggested an alternative implementation
to the Kerberos list, but the apparently-nondeterministic behavior of
access(F_OK) and stat() is nonetheless confusing and extremely difficult
to track down.
--
Geoffrey Thomas
[email protected]