I have a problem with running the following C program:
#include<unistd.h>
void main()
{
if (access("/root/main.c",R_OK)==0)
{
printf("/root/main.c can be read\n");
}
else
{
printf("can't be read\n");
}
}
When I run the executable as root, I can get the output:
/root/main.c can be read
But when I set the executable's permissions to 4755, and run it as normal user, I only get the output:
can't be read
Is there any error in my protocol?
access ignores setuid/setgid bits. This is by design.
Quoting from man 2 access on Linux:
The check is done using the calling process's real UID and GID,
rather than the effective IDs as is done when actually attempting an
operation (e.g., open(2)) on the file. Similarly, for the root user,
the check uses the set of permitted capabilities rather than the set
of effective capabilities; and for non-root users, the check uses an
empty set of capabilities.
This allows set-user-ID programs and capability-endowed programs to
easily determine the invoking user's authority. In other words,
access() does not answer the "can I read/write/execute this file?"
question. It answers a slightly different question: "(assuming I'm a
setuid binary) can the user who invoked me read/write/execute this
file?", which gives set-user-ID programs the possibility to prevent
malicious users from causing them to read files which users shouldn't
be able to read.
If you want to know whether your process can actually open a file for reading, just open() it and handle the error, if any. (This also avoids a race condition.)
Related
At the moment I am playing around with bluetooth LE and iBeacon devices.
I wrote an Server that keeps looking for nearby beacons.
My server follows this example (Link)
Unfortunately calling the function:
hci_le_set_scan_parameters()
requires root privileges.
As I don't want to run the whole server with root privileges I wanted to ask if there is any possibility for calling only this function with root privileges?
I am aware that asking for sudo when executing a program is always at least questionable I could not find any other possibility to scan for iBeacons.
If there is another possibility I am happy to hear about it as well.
Thanks for your help and kind regards
nPLus
According to POSIX, UID/GID are process attributes. All code inside your process is executed with UID/GID currently set for the whole process.
You could start server as root and immediately drop root privileges. Then, you can temporary gain root privileges using seteuid(2) when executing your function.
See also this answer.
You can also gain only selected capabilities(7) instead (temporary or permanently).
Thread-safety note
AFAIK, on Linux UID/GID are per-thread attributes and it's possible to set them for single thread, see NOTES section in seteuid() man-page and this post.
If you can move the privileged part into a separate process, I warmly recommend doing so. The parent process will construct at least one Unix Domain socket pair, keeping one end for itself, and put the other end as the child process standard input or output.
The reason for using an Unix domain socket pair is that such a pair is not only bidirectional, but also supports identifying the process at the other end, and passing open file descriptors from one process to another.
For example, if your main process needs superuser access to read a file, perhaps in a specific directory, or otherwise identifiable, you can move the opening of such files into a separate helper program. By using an Unix domain socket pair for communication between the two, the helper program can use getsockopt(ufd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_size) to obtain the peer credentials: process ID, effective user ID, and effective group ID. Using readlink() on the pseudofile /proc/PID/exe (where PID is the process ID as a positive decimal number) you can obtain the executable the other end is currently running.
If the target file/device can be opened, then the helper can pass the open file descriptor back to the parent process. (Access checks in Linux are only done when the file descriptor is opened. Read accesses will only be blocked later if the descriptor was opened write-only or the socket read end has been shut down, and write accesses only blocked if the descriptor was opened read-only or the socket write end has been shut down.)
I recommend passing an int as the data, which is 0 if successful with the descriptor as an ancillary message, and an errno error code otherwise (without ancillary data).
However, it is important to consider the possible ways how such helpers might be exploited. Limiting to a specific directory, or perhaps having a system-wide configuration file that specifies allowed path glob patterns (and not writable by everyone), and using e.g. fnmatch() to check if the passed path is listed, are good approaches.
The helper process can gain privileges either by being setuid, or via Linux filesystem capabilities. For example, giving the helper only the CAP_DAC_OVERRIDE capability would let it bypass file read, write, and execute checks. In Debian derivatives, the command-line tool to manipulate filesystem capabilities, setcap, is in the libcap2-bin package.
If you cannot move the privileged part into a separate process, you can use the interface supported in Linux, BSDs, and HP-UX systems: setresuid(), which sets the real, effective, and saved user IDs in a single call. (There is a corresponding setresgid() call for the real, effective, and saved group IDs, but when using that one, remember that the supplementary group list is not modified; you need to explicitly call setgroups() or initgroups() to modify the supplementary group list.)
There are also filesystem user ID and filesystem group ID, but the C library will set these to match the effective ones whenever effective user and/or group ID is set.
If the process is started with superuser privileges, then the effective user ID will be zero. If you first use getresuid(&ruid, &euid, &suid) and getresgid(&rgid, &egid, &sgid), you can use setresgid(rgid, rgid, rgid) to ensure only the real group identity remains, and temporarily drop superuser privileges by calling setresuid(ruid, ruid, 0). To re-gain superuser privileges, use setresuid(0, ruid, 0), and to permanently drop superuser privileges, use setresuid(ruid, ruid, ruid).
This works, because a process is allowed to switch between real, effective, and saved identities. Effective is the one that governs access to resources.
There is a way to restrict the privilege to a dedicated thread within the process, but it is hacky and fragile, and I don't recommend it.
To keep the privilege restricted to within a single thread, you create custom wrappers around the SYS_setresuid/SYS_setresuid32, SYS_setresgid/SYS_setresgid32, SYS_getresuid/SYS_getresuid32, SYS_getresgid/SYS_getresgid32, SYS_setfsuid/SYS_setfsuid32, and SYS_setfsgid/SYS_setfsgid32 syscalls. (Have the wrapper call the 32-bit version, and if it returns -ENOSYS, fall back to the 16-bit version.)
In Linux, the user and group identities are actually per-thread, not per-process. The standard C library used will use e.g. realtime POSIX signals and an internal handler to signal other threads to switch identity, as part of the library functions that manipulate these identities.
Early in your process, create a privileged thread, which will keep root (0) as the saved user identity, but otherwise copy real identity to effective and saved identities. For the main process, copy real identity to effective and saved identities. When the privileged thread needs to do something, it first sets the effective user identity to root, does the thing, then resets effective user identity to the real user identity. This way the privileged part is limited to this one thread, and is only applied for the sections when it is necessary, so that most common signal etc. exploits will not have a chance of working unless they occur just during such a privileged section.
The downside to this is that it is imperative that none of the identity-changing C library functions (setuid(), seteuid(), setgid(), setegid(), setfsuid(), setfsgid(), setreuid(), setregid(), setresuid(), setresgid()) must be used by any code within the process. Because in Linux C library functions are weak, you can ensure that by replacing them with your own versions: define those functions yourself, with the correct name (both as shown and with two underscores) and parameters.
Of all the various methods, I do believe the separate process with identity verification through an Unix domain socket pair, is the most sensible.
It is the easiest to make robust, and can be ported between POSIX and BSD systems at least.
I noticed the hard way that the access(2) system call uses the real and not effective user ID for the access control check. While this is in line with what the access(2) man page says on Linux, it still makes little sense to me...
For example, a setuid root program would run under the effective UID of root and real UID of whoever ran the program..now, the program would be able to open /etc/shadow with open(2), but the call access("/etc/shadow", R_OK); would fail with EACCESS
Can anyone educate my on why access(2) works the way it does?
The simplest answer is that access() works the way the standard says it should:
The access() function shall check the file named by the pathname pointed to by the path argument for accessibility according to the bit pattern contained in amode, using the real user ID in place of the effective user ID and the real group ID in place of the effective group ID.
The standard also describes a different function faccessat() which has an option to use the effective UID:
AT_EACCESS
The checks for accessibility are performed using the effective user and group IDs instead of the real user and group ID as required in a call to access().
There is also a nonstandard function eaccess() or euidaccess() which you'll find on some systems, which checks using the EUID. The standard talks a bit about this function and why it's not part of the standard.
As for why access() was original designed the way it was, consider that typical programs don't actually need access() very often. If you want to know if you can open a file, it's probably because you're about to open it. So just try to open it and see if it works. It's rare to need to test whether you can do something without actually doing it.
The rationale on the standards page hints at the original purpose for access():
The superuser has complete access to all files on a system. As a consequence, programs started by the superuser and switched to the effective user ID with lesser privileges cannot use access() to test their file access permissions.
The original purpose of access() was for a setuid program to test whether the user could perform an action without considering the program's elevated access. That permits a setuid program to limit the scope of what it does without relinquishing its elevated status.
Per the Linux man page, "This allows set-user-ID programs to easily determine the invoking user’s authority."
I suppose this is actually the crux of the function. Any program can just attempt the desired type of access and handle failure if it happens. Most do. You need to check access separately only if you care whether the answer differs from what you would get from the "try and see" approach.
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?
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.
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".
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
access() Security Hole
I quote from man page access(2):
Warning: Using access() to check if a user is authorized to, for example, open a file before actually doing so using open(2) creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. For this reason, the use of this system call should be avoided.
What does this mean, and in what situation would it be a concern?
It is a classic "Time of check to time of use" race condition.
This is a security concern only for Set-user-ID and set-group-ID applications. For applications running as the user itself there is no threat, because the operation in question would be rejected by the operating system anyway.
Consider this scenario: you have a UNIX program running as root via set-user-id. The program uses access to check file permissions of another user, and then runs the file as root, but only if the permission check has been successful. Let's say the program is called securerun, and you run it as follows:
securerun myfile
An attacker can make a program that exploits this security hole to run, using this algorithm:
Write a file xyz of which the user has executing permissions
Start two threads, A and B
Thread A waits a few milliseconds, and executes cp norunning xyz to replace xyz with a file that the attacker wants to run, but has no run permissions to do so
Thread B calls securerun xyz
If the attacker gets lucky by getting his timing right, your securerun would check the execute permissions on the old xyz, but it would run the new xyz, a copy of norunning that the hacker wasn't supposed to run. Since there is a short time window between the check and the execution, the attacker is bound to get lucky at some point, if he tries his strategy many times in a loop.
Typical erroneous code:
Use access to check whether to read file on user's behalf, in a program running with elevated privileges
Short gap here
Open file
During the "short gap", the user might be able to manipulate the file system, for example:
ln -f secret_file.txt non_secret_file.txt
Then open will open the secret file for reading, even though it would have failed the access check had the link been in place at the time the check was done.
Is there a way to determine if the process may execute a file without having to actually execute it (e.g. by calling execv(filepath, args) only to fail and discover that errno == EACCES)?
I could stat the file and observe st_mode, but then I still don’t know how that pertains to the process.
Ideally, I’m looking for a function along the lines of
get_me_permissions(filepath, &status); // me: the process calling this function
// when decoded, status tells if the process can read, write, and/or execute
// the file given by filepath.
Thanks in advance.
Assuming your end goal is to eventually execute the program, you don't. This test would be useless because the result is potentially wrong even before the function to make the check returns! You must be prepared to handle failure of execve due to permission errors.
As pointed out by Steve Jessop, checking whether a given file is executable can be useful in some situations, such as a file listing (ls -l) or visual file manager. One could certainly think of more esoteric uses such a using the permission bits of a file for inter-process communication (interesting as a method which would not require any resource allocation), but I suspect stat ("What are the permission bits set to?") rather than access ("Does the calling process have X permission?") is more likely to be the interesting question...
http://linux.die.net/man/2/access
Note the slight tricksiness around suid - if the process has effective superuser privilege it isn't taken into account, since the general idea of the function is to check whether the original invoking user should have access to the file, not to check whether this process could access the file.