Unix Universe ■ The receipt
Run tcpdump on a FreeBSD box and watch it for a moment. Before the first packet arrives, the process does something quietly radical: it opens its capture device and its output file, trims the rights on both descriptors down to the operations it will actually need, and then calls cap_enter(). From that instant the filesystem no longer exists for it. The network namespace no longer exists. The process table no longer exists. If an attacker owns tcpdump through a malformed packet after that point, and malformed packets are rather tcpdump's line of work, they own a process that can write to one file and read from one device, in a world containing nothing else.
int fd = open("/var/log/capture.pcap", O_WRONLY);
cap_rights_t rights;
cap_rights_init(&rights, CAP_WRITE, CAP_SEEK);
cap_rights_limit(fd, &rights);
cap_enter(); /* no return, ever */
write_packets(fd); /* the world is now one descriptor wide */
Two lines of C bought that. Nobody announced it, nobody asked you to configure it, and it has worked this way since 2014.
The complaint this piece answers is an old one: that FreeBSD's isolation story begins and ends with jails, and jails are too coarse for the modern world, where one wants a single process confined rather than a whole environment stood up. The complaint has the story exactly backwards. The base system answers the isolation question twice, at two different grains, and the fine one has been in the kernel longer than most container platforms have existed.
Four systems, one instinct
Step back once, because the pattern is bigger than one operating system.
On 14 March 2000, FreeBSD 4.0 shipped jails: Poul-Henning Kamp's answer to a hosting provider's problem, presented with Robert Watson at SANE 2000 in Maastricht under a title that names the disease, Confining the Omnipotent Root. One kernel abstraction, one configuration, a thing that either exists or does not. Sun reached the same conclusion independently: Zones went into beta in February 2004 and shipped with Solaris 10 in early 2005, a complete environment boundary, delivered finished. OpenBSD arrived from a third direction in 2015, when Theo de Raadt proposed a system call for processes to renounce their own privileges; it spent one month under the name tame before becoming pledge, and today it threads through the entire OpenBSD source tree.
Three teams, three decades of separation in style and temperament, no code shared, and one instinct: isolation is the operating system's job, and it ships finished, in the base system, under the same release cycle as the kernel that enforces it.
The counterexample assembled itself elsewhere, and honesty requires the full sentence: Linux built namespaces one at a time between 2002 and 2013, mount first, user last, each useful alone, composition left to whoever came along. That produced flexibility no monolithic boundary offers, and an ecosystem won on merit. It also produced a decade of escape stories that almost never involve a hole in any single namespace. They involve the seams: a namespace forgotten, a capability too many, a descriptor inherited. When assembly is the user's job, assembly errors are the user's attack surface.
The coarse grain, priced
The jail is the environment-sized answer, and on ZFS it is cheaper than its reputation.
A thin jail is a clone of a base-system snapshot. The clone takes milliseconds regardless of the base system's size, occupies roughly five megabytes until it diverges, and is a first-class filesystem: snapshot it, roll it back, send it to another machine, destroy it with one command. A thick jail with its own userland runs to about ninety-one megabytes. Above both sits bhyve for the cases that genuinely need a foreign kernel. Three sizes, one operating system, no daemon between you and any of them.
That last clause carries more weight than it seems to. Nothing supervises jails except the kernel, so there is no management process whose crash takes every tenant with it, no root daemon whose socket is a privilege escalation waiting for its CVE, no registry between you and your own filesystem. The restriction is enforced where it cannot be argued with, at the system-call boundary.
What a jail cannot do, by design, is shrink to fit one process. It is an environment, and an environment was the wrong size for the tcpdump problem. Which is why the same base system grew a second grain.
The fine grain, fourteen years on
In 2010, Robert Watson and Jonathan Anderson at Cambridge presented Capsicum at USENIX Security and took Best Student Paper for it. The idea inverts the usual sandbox. Instead of writing a policy that lists what a process may not do, the process opens what it needs, limits each descriptor to the operations it will perform, and enters capability mode. There is no way back and no policy file, because there is no policy: the world simply contracts to the descriptors in hand.
FreeBSD 9.0 carried it experimentally. Since 10.0, in 2014, it has been compiled into the kernel of every FreeBSD system by default, and the list of base utilities that use it reads like a day's ordinary work: tcpdump, dhclient, hastd, kdump, ctld, iscsid, rwhod, even uniq. The pattern in each is the same and fits in a code review: open, limit, enter, work. Where a confined process still needs something global, name resolution being the usual case, a small daemon called Casper provides it through a capability, and Casper's own services run sandboxed in turn.
Put the two grains side by side and the shape of the design appears. The jail confines an environment you give to somebody else: a tenant, a service, a customer. Capsicum confines a process you run yourself, against the day its input turns hostile. The jail is a landlord's tool. Capsicum belongs to the programmer who has read their own parser and drawn the obvious conclusion. A system that ships both, in the base, under one release cycle, has not answered the isolation question narrowly. It has answered it twice, at the two sizes the question actually comes in.
When assembly is the user's job, assembly errors are the user's attack surface.
The door for everyone else
The standing objection was never about the kernel. It was about the front door: all of this lived in configuration files and the shell, and the shell is a fine interface for people who already know what a jail is.
It still is, and nothing here retires it. jail.conf, jexec, zfs clone: the complete surface, scriptable, unchanged for a decade, correct in handbook editions old enough to vote. What the ecosystem produced over the years for everyone else was a procession of managers with uneven lifespans, each solving part of the problem, none of them something you could put in front of a person meeting FreeBSD for the first time.
Since this spring there is Sylve: a management plane in Go and Svelte, first released at the end of Q1 2026 and moving quickly, that puts jails, bhyve and ZFS behind one web interface. Templates, clones, snapshots, clustering, scheduled replication, a terminal in the browser. Two lines in its description do the arguing. It installs with pkg install sylve, and it requires nothing outside the base system. A management tool that adds no dependency tree is rare enough in this decade to be worth writing down, and the FreeBSD Foundation is among those backing it.
The shell remains concept one. Sylve is the second door, for the hands that want one, and the building did not move to accommodate it.
The limit
Now the other side of the ledger, because there is one.
Capsicum works only where the author of the program put it there, and fourteen years after it entered the kernel by default, the list of programs that call cap_enter() remains short. Sandboxing a process this way means restructuring it around its descriptors, which is real work, and most upstream software is written for the operating system it already runs on. The elegant mechanism nobody adopts is a recurring Unix genre, and Capsicum has spent years flirting with membership.
Sylve is young: first release this spring, version zero point two something as this is written. Promising is a description, and it is not the same description as proven.
And where the target kernel is Linux, none of this is on the table, which settles the question for a large share of the industry before it is asked. The point was never that the industry chose wrong. The point is that the complaint about coarseness was answered in the base system eleven years ago, and the answer has been running on every FreeBSD machine since, two lines above the packet loop, without once asking for attention.
The next time somebody tells you process isolation was invented in 2013 and requires a daemon, run tcpdump and consider what it gave up before the first packet arrived.