Reputation: 13121
The Linux function access()
allows me to check file permissions for the current user.
Is there a similar function that gives me the same information - but instead of checking the current user it checks the permissions of any given system user?
Something like int access_for(const char *pathname, uid_t uid, int mode);
or whatever
I can't use seteuid()
as I need this for a multithreaded process (POSIX threads) which would affect all threads at the same time. That's why I need to check file permissions myself.
Edit: The process itself is known/assumed to have at least the privileges of the relevant user. So, in theory I could also walk the file system and calculate the rights by hand, but I'd need something much more efficient as the check needs to be done several (up to hundreds) times per second. Possible?
Upvotes: 1
Views: 281
Reputation: 129464
Beware of TOCTOU. If you check NOW that a file can be accessed, it doesn't mean that NOW it can (or can't), because the time it took you to read those words between "NOW" and "NOW", the file privileges may well have changed.
So, the CORRECT solution is to run in a thread/process as the user that you want to access the file as. Otherwise, you run a risk of "the file privileges changed while you were working" problem.
Of course, this applies to any type of access to "things that may be restricted based on who I am running as".
Upvotes: 2
Reputation: 215427
On Linux, fundamentally all set*id
operations are thread-local. This is wrong and non-conforming (the standard specifies that a process, not a thread, has ids that are set by these functions) and the userspace code (in libc) has to work around the issue via delicate and error-prone logic to change all the thread uids in a synchronized way. However, you may be able to invoke the syscall directly (via syscall()
) to change the ids for just one thread.
Also, Linux has the concept of "filesystem uid" set by the setfsuid
function. If I'm not mistaken, libc leaves this one thread-local, since it's not specified by any standard (and thus does not have any requirements imposed on it) and since the whole purpose of this function is thread-local use like what you're doing. I think this second option is much better if it works.
Finally, there's one solution that's completely portable but slow: fork
then use seteuid
in the child, call access
there, pass the result back to the parent, and _exit
.
Upvotes: 1
Reputation: 360762
not sure how it could work. if you're running as user X, you couldn't reliably check if user Y has access to something, because the check would be done under YOUR permissions. You may not have access to something that Y
does, meaning you'd get a false negative.
Upvotes: 2