limit number of forks/child procs - linux

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).

Related

Is this possible to switch the user and group of an application thread?

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.

Shorting the time between process crash and shooting server in the head?

I have a routine that crashes linux and force a reboot using a system function.
Now I have the problem that I need to crash linux when a certain process dies. Using a script starting the process and if the script ends restart the server is not appropriate since it takes some ms.
Another idea is spawning the shooting processes alongside and use polling of a counter and if the counter is not incremented reboot the server would be another idea.
This would result in an almost instant reaction.
Now the question is what would be a good timeframe. I have no idea how the scheduler of linux would guarantee a certain update of any such counter and what a good timeout would be.
Also I would like to hear some alternatives to this second process spawning. Is there a possibility to advice linux to run a certain routine in case of a crash of the given process or a listener meachanism for the even of problems with a given process?
The timeout idea is already implemented in the kernel. You can register any application as a software watchdog, but you'll have to lower the default timeout. Have a look at http://linux.die.net/man/8/watchdog for some ideas. That application can also handle user-defined tests. Realistically unless you're trying to run kernel like linux-rt, having timeouts lower than 100ms can be dangerous on a system with heavy load - especially if the check needs to poll another application.
In cases of application crashes, you can handle them if your init supports notifications. For example both upstart and systemd can do that by monitoring files (make sure coredumps are created in the right place).
But in any case, I'd suggest rethinking the idea of millisecond-resolution restarts. Do you really need to kill the system in that time, or do you just need to isolate it? Just syncing the disks will take a few extra milliseconds and you probably don't want to miss that step. Instead of just killing the host, you could make sure the affected app isn't working (SIGABRT?) and kill all networking (flush iptables, change default to DROP).

Need weird advice in how to allow a Linux process ONLY create and use a single pipe

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.

Change UID/GID only of one thread in Linux

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)!

How can I manage use of a shared resource used by several Perl programs?

I am looking for a good way to manage the access to an external FTP server from various programs on a single server.
Currently I am working with a lock file, so that only one process can use the ftp server at a time. What would be a good way to allow 2-3 parallel processes to access the ftp server simultaneously. Unfortunately the provider does not allow more sessions and locks my account for a day if too many processes access their server.
Used platforms are Solaris and Linux - all ftp access is encapsulated in a single library thus there is only 1 function which I need to change. Would be nice if there is something on CPAN.
I'd look into perlipc(1) for SystemV semaphores or modules like POSIX::RT::Semaphore for posix semaphores. I'd create a semaphore with a resource count of 2-3, and then in the different process try to get the semaphore.
Instead of making a bunch of programs wait in line, could you create one local program that handled all the remote communication while the local programs talked to it? You effectively create a proxy and push that complexity away from your programs so you don't have to deal with it in every program.
I don't know the other constraints on your problem, but this has worked for me on similar issues.

Resources