FreeBSD Capsicum requires a file-descriptor rights design

2026-11-12来源 dev.toEnglish

FreeBSD Capsicum requires a file-descriptor rights design

Capsicum changes the security model for a FreeBSD process by moving authority into delegated descriptors. After cap_enter(2), the process cannot freely reach global namespaces such as the filesystem or process table. It can operate through file descriptors and other capabilities it already holds. That model is useful for parsers and network services, but the boundary is only as good as the rights attached to every inherited descriptor.

A common mistake is to treat capability mode as a filesystem chroot. The process may still use an already open directory, socket, pipe, or shared-memory object. Those handles can carry broad authority. The relevant review therefore starts before cap_enter(): what descriptors exist, what rights do they retain, and which code paths can use them after confinement?

FreeBSD's capsicum(4) manual describes a process mode that restricts access to global namespaces and permits operations only through explicitly delegated rights, memory mappings, or descriptors. The cap_enter(2) manual also warns that inherited VM resources, memory contents, and process properties need consideration. Entering the mode does not erase authority that arrived through inheritance.

Limit rights before entering capability mode

The design should open required objects, reduce their rights with the Capsicum rights interfaces, and then enter capability mode. A service that needs to read a directory can retain directory lookup and read rights without retaining create, delete, or rename operations. A socket can be limited to the operations the protocol handler needs. A helper that only renders data should have no path for opening arbitrary files after startup.

This is more than a list of flags. Each descriptor needs an owner and a lifecycle. A listener socket may be passed to a worker, but a database configuration file should not remain open just because startup opened it. The worker should receive a narrow handle or no handle at all. Code that stores a global descriptor for a later administrative action creates a capability that may survive the intended privilege drop.

The FreeBSD framework also includes libcasper helpers and process-descriptor tools for separating privileged operations from a sandboxed consumer. Those helpers deserve the same audit as an in-process API. A helper that accepts arbitrary paths recreates the global namespace access that capability mode was meant to remove. A helper with a fixed operation and validated arguments can be a deliberate broker.

Verify the boundary with denied operations

Test after confinement, not only during startup. Try to open a new path. Try to create a child process or inspect a process outside the descriptor set. Try to use a retained socket for an operation that should have been removed by the rights limit. Confirm the operation fails with the expected error and that the service records enough context to diagnose a legitimate missing capability.

Tests should also cover descriptor inheritance through fork, exec, and worker threads. A descriptor that is accidentally inherited can cross a component boundary even if the original code never intended to share it. Check close-on-exec behavior and the explicit set of descriptors passed to workers. A capability architecture is easier to review when the launch code documents every descriptor and the code that consumes it.

Keep the design narrow after confinement

Some operations cannot be performed inside a strict capability sandbox. File discovery for a dynamic directory tree, DNS resolution through system libraries, and user lookup may require a broker. That is a design decision, not a reason to leave the main parser unrestricted. Move the need into a small service with a fixed protocol, validate the request against an allowlist, and return only the result the consumer needs.

The most useful Capsicum review asks what the process can still do after it enters the mode. If the answer includes opening an arbitrary path, inheriting a privileged descriptor, or contacting an unconstrained administrative service, the boundary is incomplete. The implementation should make those remainders explicit and justify each one against the data the process handles.

Capability mode reduces the consequences of a memory-safety or parser failure only when the available capabilities are already small. The deployment evidence is a rights inventory, tests for denied operations, and a launch path that passes only validated descriptors into the sandbox.

References

原文:https://www.a8q9.cn/en/article/freebsd-capsicum-requires-a-file-descriptor-rights-design-9e5513.html

相关文章