Sandboxing for dummies: Process isolation, seccomp and writing good policies

renatoboo1 pts0 comments

renato's cyberspace - Sandboxing: Process isolation, seccomp and policies

renato's cyberspace

--><br>-->

posts

--><br>-->

about

> Sandboxing: Process isolation, seccomp and policies

tags:<br>#linux,

#application-security

This page was last updated at 2026-05-27 15:31:36 UTC.

Little boxes all the same<br>[…]<br>And they all get put in boxes, and they all come out the same<br>Pete Seeger - Little Boxes

Hello netizens,

I’ve decided to write an exploratory article about linux processes, containers and seccomp applicability. Although all these concepts already have been talked about in depth, I still feel that rarely we see an article linking those concepts together from a foundational pov.

Understanding process isolation and seccomp helps us build a strong sandboxing foundational knowledge. Sandboxing is everywhere: From your processes, containers and browsers.

Each topic is huge in itself, so I’m also using this as an exercise to deliberately explore each concept and keep it as simple as possible.

Hope this is a wall of text worth reading!

Processes: Families

In Linux everything is either a file or a process.

Let’s talk biology: Processes live inside your Linux box and can reproduce via the fork() call. When a process calls fork() that process becomes the parent process and spawns a child process. Just like biology, this child inherits characteristics of its parents segments (Text, Data, Heap and Stack). ;)

The child process goes to execute different functions in the same code as the parent, or can spawn different programs. Let’s take running the ps command for example. If we run the program with the tree printing, we can see every parent of our process, just like a family tree:

ps xao user,pid,ppid,pgid,sid,command --forest<br>#USER PID PPID PGID SID COMMAND<br>#root 1 0 1 1 /sbin/init<br>#root 2 1 0 0 /init<br>#root 6 2 0 0 \_ plan9 --control-socket 7 --log-level 4 --server-fd 8 --pipe-fd 10 --log-truncate<br>#root 539 2 539 539 \_ [SessionLeader]<br>#root 546 2 546 546 \_ /bin/login -f<br>#renato 624 546 624 546 | \_ -zsh<br>#root 553 2 553 553 \_ /init<br>#root 554 553 553 553 | \_ /init<br>#renato 555 554 555 555 | \_ -zsh<br>#renato 32965 555 32965 555 | \_ ps xao user,pid,ppid,pgid,sid,command --forest

Every column above represents the characteristics of the process: You have the process identification (PID), their parents’ identification (PPID), their family group (PGID) and the house they live in / session (SID).

Just like Pete’s Seeger song, each process can live inside its own neat little box and be completely alienated from the rest of the other processes. This is where namespaces and cgroups come in.

Namespaces and cgroups: Neighborhood and resources

I used to think that “namespaces” were a Linux thing, but I found that the namespace itself is not Linux specific and could be very broad. It turns out that namespace is literally putting “related things” into a box.

In computing, a namespace is a set of signs (names) that are used to identify and refer to objects of various kinds.<br>Wikipedia - Namespace

Think of namespaces as a neighborhood: Each individual house has its own resources (utilities) but they share the same street. They all pay share the same underlying public utility infrascture (water, gas, electricity). This isolation (namespaces) are what makes residents of this neighborhood have access to common shared infrastructure / resources. One or many processess can live under the same namespace.

Linux Namespaces limit what resources a process can see.

In this case: If our linux box is a city, container is the neighborhood and its inhabitants are families. A container is a namespaced process. And each process inside is namespaced by the container.

docker run --rm -dit --name nstest busybox sh<br>docker top nstest<br>#UID PID PPID C STIME TTY TIME CMD<br>#root 484 461 0 10:14 pts/0 00:00:00 shdocker inspect --format '' sectest<br>docker exec nstest ps aux<br>#PID USER TIME COMMAND<br># 1 root 0:00 sh<br># 7 root 0:00 ps aux

In the penguin hood these are the namespaces available to processes and what they are allowed to “see and share”:

PID → This allows for process isolation to take place: Many process can be a part of a single process just like a container.

NET → Limits networking like interfaces, packets and routes.

MNT → Mount, used for filesystem.

UTS → Hostname and domain name.

IPC → Interprocess Communication.

USER → UID and GID mappings.

TIME → Time related, like literally clock stuff.

CGROUP → Control groups.

If we check the namespace of our current process vs the docker image we just created, we can see that they see different resources and are allowed to consume different things. Different inodes mean different namespaces.

ls -la /proc/self/ns/<br>#total 0<br>#dr-x--x--x 2 renato renato 0 May 12 19:05 .<br>#dr-xr-xr-x 9 renato renato 0 May 12 19:05 ..<br>#lrwxrwxrwx 1 renato renato 0 May 12 19:05 cgroup -> 'cgroup:[4026531835]'<br>#lrwxrwxrwx 1 renato renato 0 May 12 19:05 ipc -> 'ipc:[4026532206]'<br>#lrwxrwxrwx 1 renato renato 0...

process renato root linux namespaces isolation

Related Articles