Linux System Programming · intermediate · ~15 min
Learn to set resource limits on your own process before escalating privileges or entering a sandbox.
setrlimit puts a per-process cap on a single resource, such as memory or CPU time.
Each resource has two limits:
Once you lower the hard limit, only root can raise it again. This is a one-way door, which makes it useful for dropping your own privileges before running risky code.
Sandboxing in C starts with resource limits.
Every Docker container, every CI runner, and every code-execution service tunes them to keep workloads contained.
mmap'd regions). This effectively caps how much malloc can hand out.SIGXCPU when the soft limit is reached, and SIGKILL at the hard limit.SIGXFSZ.When auditing a sandbox runner, check whether it sets resource limits at all.
RLIMIT_CPU means an attacker can pin a CPU core forever.RLIMIT_AS means an attacker can exhaust memory and trigger the out-of-memory (OOM) killer.Lower both the soft and hard limits at the start of a section that runs with privileges before dropping them.
Never raise a hard limit that you set yourself. You cannot, unless you are root.
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
getrlimit reads the current limits for a resource. setrlimit changes them.
setrlimit and getrlimit configure per-process resource caps: CPU seconds, address space, file size, and number of open file descriptors.
They are the user-space foundation of every sandbox, including ours.
struct rlimit r = { .rlim_cur = 128 * 1024 * 1024, .rlim_max = 128 * 1024 * 1024 };
setrlimit(RLIMIT_AS, &r); /* 128 MB max address space */
struct rlimit r;
r.rlim_cur = r.rlim_max = 5; /* 5 CPU-seconds */
setrlimit(RLIMIT_CPU, &r);
r.rlim_cur = r.rlim_max = 128 * 1024L * 1024L; /* 128 MB */
setrlimit(RLIMIT_AS, &r);
Several tools let you inspect resource limits:
ulimit -a in a shell shows your current limits.prlimit --pid PID queries any running process.cat /proc/PID/limits shows the kernel's view for a given process.Setting RLIMIT_AS too low can make a later malloc fail in ways you did not expect.
Always test under realistic load before relying on a tight limit.
ulimit.RLIMIT_AS to 128 MB, then watch a 200 MB malloc fail.RLIMIT_CPU to 5 seconds, then run an infinite loop and observe the process being killed.RLIMIT_NOFILE to 16, then watch the 17th open call fail.setrlimit caps a per-process resource (CPU, memory, file size, open fds).