Is there a way to change UID/GID only of one thread in a multithreaded process?
The reason for this is writing a file-serving application - the ACL's and quota are not enforced unless the uid/gid of the caller is set to the correct user, new files/directories are not created with correct uid/gid etc.
The network applications can usually fork() themselves at the beginning and process each user request in separate process. If there is a need for shared data, it must go through some kind of shared memory. However, e.g. the FUSE (linux user filesystem) by default uses multithreading and in conjuction with python bindings it wouldn't be practical to try to use a forking model.
The 'consistent' UID for a whole process seems to be according to the POSIX standard, however old Linuxes didn't follow the POSIX and allowed different uids for different threads. The new kernels seem to follow POSIX, is there some way to allow the old 'broken' behaviour?
The Linux-specific setfsuid() / setfsgid() are per-thread rather than per-process. They're designed specifically for this use case (file server).
Note that access() will still check access using the real uid and gid - that is by design (it is intended to answer the question "should the user who ran this binary have the given access to this file"). For the setfsuid() / setfsgid() case you should just try the requested operation and detect failure due to lack of permission at that point.
To change the uid only for one thread you need to use the syscall directly: syscall(SYS_setresuid, ...); The libc function setresuid() will synchronize it for all threads (using a singal which it sends to all threads)!
Related
I want to build a small web application in Rust which should be able to read and write files on a users behalf. The user should authenticate with their UNIX credentials and then be able to read / write only the files they have access to.
My first idea, which would also seem the most secure to me, would be to switch the user-context of an application thread and do all the read/write-stuff there. Is this possible?
If this is possible, what would the performance look like? I would assume spawning an operating system thread every time a request comes in could have a very high overhead. Is there a better way to do this?
I really wouldn't like to run my entire application as root and check the permissions manually.
On GNU/Linux, it is not possible to switch UID and GID just for a single thread of a process. The Linux kernel maintains per-thread credentials, but POSIX requires a single set of credentials per process: POSIX setuid must change the UID of all threads or none. glibc goes to great lengths to emulate the POSIX behavior, although that is quite difficult.
You would have to create a completely new process for each request, not just a new thread. Process creation is quite cheap on Linux, but it could still be a performance problem. You could keep a pool of processes around to avoid the overhead of repeated process creation. On the other hand, many years ago, lots of web sites (including some fairly large ones) used CGI to generate web pages, and you can get relatively far with a simple design.
I think #Florian got this backwards in his original answer. man 2 setuid says
C library/kernel differences
At the kernel level, user IDs and group IDs are a per-thread attribute. However, POSIX requires that all threads in a process
share the same credentials. The NPTL threading implementation handles
the POSIX requirements by providing wrapper functions for the various
system calls that change process
UIDs and GIDs. These wrapper functions (including the one for setuid()) employ a signal-based technique to ensure that when one
thread changes credentials, all of the other threads in the process
also change their credentials. For details, see nptl(7).
Since libc does the signal dance to do it for the whole process you will have to do direct system calls to bypass that.
Note that this is linux-specific. Most other unix variants do seem to follow posix at the kernel level instead emulating it in libc.
I am working on hardening a sandbox for student code execution. I think I'm satisfied that students can't share data on the file system or with signals because I've found express rules dictating those and they execute as different unprivileged users. However, I am having a really hard time looking at documentation to determine, when shared memory (or IPC more generally - queues or semaphores) is created, who can see that. If you create shared memory, can anyone on the same machine open it, or is there a way to control that? Does the control lie in the program that creates the memory, or can the sysadmin limit it?
Any process in the same ipc namespace can see and (potentially) access ipc objects created by other processes in the same ipc namespace. Each ipc object has the same user/group/other-rwx permissions as file system objects objects -- see the svipc(7) manual page.
You can create a new ipc namespace by using the clone(2) system call with the CLONE_NEWIPC flag. You can use the unshare(1) program to do a clone+exec of another program with this or certain other CLONE flags.
I am hosting a computing service on Ubuntu 12.04 and I need a method to prevent users from forkbombing. I am currently using setrlimit(RLIMIT_NPROC) in Linux. However, this actually sets a global limit on the number of processes for a given UID. Because my service has many parallel jobs, all running with the same UID, this means that one process can DOS the entire service.
Instead I am looking for a way to set a restriction on e.g. the recursive number of child procs for the current process. I have been told to look into linux cgroups / libcgroup but I honestly don't really understand how this could solve my problem. Any tips?
The internet says that the only way to prevent (read: mitigate) fork bombs is by setting RLIMIT_NPROC. Probably because a user id is the only practical place to attach a "processes forked so far" call to.
Suggestion: Have your service run under a number of uids, and have each invocation of the service pick one. Then the ability of a rogue client to DOS via fork bombing is limited proportionately by the number of UIDs used.
You sould probably need some sort of SUID helper program to do this, unless the service's top-level process runs as root (generally considered a bad idea).
Hoi.
I am working on an experiment allowing users to use 1% of my CPU. That's like your own Webserver; but a big dynamic remote execution framework (dont ask about that), and I dont want users to use API functions like create files, no sockets, no threads, no console output, nothing.
Update1: People will be sending me binaries, so interrupt 0x80 is possible. Therefore... Kernel?
I need to limit a process so it cannot do anything but use a single pipe. Through that pipe the process will use my own wrapped and controlled API.
Is that even possible? I thought like a Linux kernel module.
The issues with limiting RAM and CPU are not primary here, for that there's something on google.
Thanks in advance!
The ptrace facility will allow your program to observe and control the operation of another process. Using the PTRACE_SYSCALL flag, you can stop the child process before every syscall, and make a decision about whether you want to allow that system call to proceed.
You might want to look at what Google is doing with their Native Client technology and the seccomp sandbox. The Native Client (NaCl) stuff is intended to let x86 binaries supplied by a web site run inside a user's local browser. The problem of malicious binaries is similar to what you face, so most of the technology/research probably applies directly.
I thought that one process cannot read the memory of other processes. But I'm shocked to see an application named "WinHex" which has "RAM Editor" and it is able to access the entire memory. Of all the processes.
How is that possible? And it is even able to modify the memory of other processes. Doesn't this become malicious?
In all likelyhood, the tool uses ReadProcessMemory or some variant, which requires PROCESS_VM_READ access.
With respect to your "malicious" comment, remember that you (or the process invoking this API, which likely needs Administrator-level permissions) already has total control over the machine. The security game is already lost at this point.
Well, that's one of the things a process with the right privileges, granted by the operating system, can do. Processes cannot access other processes' memory in principle. In practice the underlying operating system usually offers this mechanism to privileged processes.
Accessing other process' memory is a piece of cake.
You can even use Windows Driver Kit to access and modify everything.
Check out for example rootkits to see how fragile is the OS when you don't restrict programs' privileges.
If you're running as Administrator, you can obtain privileges to read all of memory; it seems that WinHex is doing this on your behalf.
Have you tried this on a more restricted account?
I think it uses some DLL injection technique.
See http://en.wikipedia.org/wiki/DLL_injection for more information