LmCast :: Stay tuned in

Capability-Based Security for Redox: Namespace and CWD as Capabilities

Recorded: March 28, 2026, 4 a.m.

Original Summarized

Capability-based Security for Redox: Namespace and CWD as capabilities - Redox - Your Next(Gen) OS

Docs
FAQ
News
Community
Donate/Merch

Matrix (protocol) logo

Capability-based Security for Redox: Namespace and CWD as capabilities
By Ibuki Omatsu

on Tuesday, March 17, 2026

Hello everyone! I’m Ibuki Omatsu. I’m currently working on the project “Capability-based security for Redox”, graciously funded by NGI Zero Commons and NLnet.
In this post, I’ll explain “Namespace management in Userspace” and “CWD as a Capability”.
We’ll explore how we reimplemented the namespace that previously was managed by the kernel, and the previously string-based CWD management, using capabilities.
You might want to read about Capability-based security if you are unfamiliar with it.
A simplified description is that an open file descriptor is a capability,
because it identifies a resource and the application’s access rights for that resource.
Capability-based security expects that all resources will be accessed starting from a capability.
Introduction: The architecture of Redox OS
In this section, I’ll explain two Redox specific concepts: resource provider “Schemes”, and our implementation of the C standard library, “relibc”.
Scheme: Resource Provider Services
As you know, Redox OS is a microkernel-based operating system.
This means most system components and drivers, such as filesystems and process managers, run as separate programs in userspace.
“Schemes” are the services that these programs provide.
For example, RedoxFS (Redox OS’s Filesystem service) provides the file scheme, and the process manager provides the proc scheme.
All resources are accesssed by a “Scheme-rooted Path” that takes following form: /scheme/{scheme-name}/{resource-name}.
Example of Scheme-rooted Paths:

file: /home/user/file.txt -> /scheme/file/home/user/file.txt
tcp: 127.0.0.1:8080 -> /scheme/tcp/127.0.0.1/8080

In Redox, the “Namespace” controls the visibility of schemes.
Schemes are registered to namespaces, and a process is only able to access the schemes registered to its own namespace.
This is controlled using Scheme-rooted path.
For example, In a namespace such as ["file", "uds"], a process can access files and Unix Domain Sockets, but it cannot access the network stack.
relibc: The C Standard Library
relibc is a C standard library, that mainly targets Redox OS, but also supports multiple operating systems.
For Linux, it simply calls raw syscalls. However, for Redox, it provides redox-rt (the Redox runtime service).
redox-rt provides a translation layer from Redox services to POSIX-compliant services (POSIX compatibility layer), and performs some of the functions typically assigned to the kernel in other Unix-like systems. It provides some features such as translation of POSIX standard path to a scheme-rooted path, and management of Redox internal file descriptors.
In Redox OS, threads and processes are managed as file descriptors by redox-rt.
File Access in Redox OS Before Capabilities
Let’s look back at how file access worked before the transition to capabilities.
In this previous design, the namespace existed in the kernel, and was bound to the process by an integer ID.
Absolute Path

Application calls open("/home/user/some_file").
relibc (redox-rt) converts the path to scheme-rooted Path /scheme/file/home/user/some_file, and opens it.
The kernel extracts the target scheme name file, and looks for it in the caller process’s namespace.
If the target scheme file is registered in the namespace, the kernel routes the system call request to the scheme.
file scheme receives the system call request.

In this design, where the kernel manages both Scheme and Namespace, the kernel has to hold all scheme names as strings and parse the paths to identify the target scheme.

Figure 1: File access flow before capabilities.

Relative Path (CWD)
Previously, a relative path was always converted to an absolute path before begin processed.
Because relibc stored the CWD as a string, all relative paths were converted to absolute paths by joining it to the CWD string.
In this previous design, we had to reconstruct an absolute path every time a relative path was provided. This also made it challenging to apply restrictions, such as O_RESOLVE_BENEATH, to the CWD.
Our goal is to solve these issues caused by path-based management.
The key of this transition is the openat system call.
Key Concept: openat(dir_fd, path)
The openat system call opens a file, ralative to a directory file descriptor.
In an unrestricted mode, this is just a convenience.
However, If we limit the paths to be beneath that dir_fd, and restrict a program to use only openat, the dir_fd effectively becomes a sandbox.
The program cannot see or access anything outside of that directory.
Namespace Manager in Userspace
Based on openat, we have introduced a Namespace Manager (nsmgr) in userspace.
In this new design, nsmgr is an userspace scheme-type service daemon, and sits between the application and other schemes.
The namespace is represented as a file descriptor managed by redox-rt, rather than just an ID bound to the process.
pub struct DynamicProcInfo {
pub pgid: u32,
...
pub sgid: u32,
pub ns_fd: Option<FdGuardUpper>,
}
Here is the sequence.

An application calls open("/home/user/some_file").
relibc (redox-rt) converts the path to a scheme-rooted Path ("/scheme/file/home/user/some_file" in this case), and then calls openat with the process’s namespace file descriptor as the dir_fd.
nsmgr receives the openat request.
nsmgr extracts the target scheme name (file), and looks for it in the namespace bound to the file descriptor.
If the target scheme file is registered in the namespace, the nsmgr daemon routes the openat request to the scheme.
file scheme receives the openat request, and sends an file descriptor for the file to nsmgr.
nsmgr forwards the file descriptor to the application. nsmgr does not need to participate in any future operations on the new file descriptor.

Figure 2: File access flow after capabilities.

Applications only operate relative to their provided namespace file descriptor.
This allows us to remove complex scheme and namespace management from the kernel.
Schemes are created anonymously in the kernel, this means the kernel no longer needs to know any scheme names.
The kernel now only needs to dispatch the system call requests to the schemes, based on the dir_fd, and doesn’t need to parse paths.
CWD as a Capability
Similarly, we updated relibc to handle the CWD as a capability.
Now, relibc holds the CWD as a file descriptor, not just a string path.
When an application passes a relative path to open, or when an AT_FDCWD is passed to the libc openat function, relibc simply calls its internal openat using the CWD file descriptor.
Due to this transition, we can process relative paths without converting them to absolute paths.
And we become able to support O_RESOLVE_BENEATH with a simple implementation.
When we set the flag on the file descriptor, the scheme will limit the use of ../ to prevent escaping the sandbox.
In addition, we can use the CWD file descriptor as a sandbox, by restricting absolute path access via the namespace.
pub struct Cwd {
pub path: Box<str>,
pub fd: FdGuardUpper,
}
Note that for getcwd(), we still cache the CWD path string.
However, this may change as we implement more sandboxing features.
Conclusion
By reimplementing these features using capabilities, we made the kernel simpler by moving complex scheme and namespace management out of it which improved security and stability by reducing the attack surface and possible bugs. At the same time, we gained a means to support more sandboxing features using the CWD file descriptor.
This project leads the way for future sandboxing support in Redox OS.
As the OS continues to move toward capability-based security, it will be able to provide more modern security features.
Thank you for reading this post, and I hope you found it informative and interesting.

Redox OS

Home
Documentation
News
Community
Merchandise
RSoC

Resources

Quickstart
Gallery
GitLab
Book
Packages
Meeting Minutes

Matrix (protocol) logo

English

中文
Español
Русский
Français
Deutsch
Italiano
Türkçe
Svenska
Nederlands
Dansk
Norsk
Čeština
Esperanto
Português
日本語
한국어
Magyar
Polski
Українська
العربية

Copyright © 2015-2025 by The Redox Developers.
Redox OS is a trademark of the Redox OS nonprofit.

Trademark  
Contributing  
License

Capability-based Security for Redox: Namespace and CWD as Capabilities – A Detailed Summary

Ibuki Omatsu, in this document, outlines a significant architectural shift within Redox OS, moving away from kernel-managed namespaces and string-based CWD management towards a capability-based system. This redesign, funded by NGI Zero Commons and NLnet, aims to enhance security, stability, and support for advanced sandboxing features. This summary details the key changes and rationales behind them.

The core concept driving this transition is capability-based security, where resources are accessed through explicit capabilities – essentially, open file descriptors – rather than relying on traditional file permissions. This approach, as described, significantly reduces the attack surface by limiting access to only those resources granted through a capability.

Redox OS’s architecture is fundamentally microkernel-based, with most system components and drivers – including filesystems and process managers – running in userspace. The system leverages “Schemes” to provide these services. Schemes, such as RedoxFS and the process manager, are accessed via “Scheme-rooted Paths” (e.g., /scheme/file/home/user/file.txt), which control the visibility of these services to processes. The namespace, critically, governs this visibility, restricting access based on scheme registration.

The previous design relied on relibc – the C standard library – to translate POSIX calls and manage file access. It utilized a kernel-managed namespace, bound to processes via integer IDs, alongside string-based CWD management. This involved parsing paths, converting them to scheme-rooted paths, and holding all scheme names within the kernel.

The new architecture dramatically simplifies this. It introduces a Namespace Manager (nsmgr) in userspace, a scheme-type service daemon that sits between applications and other schemes. The namespace is now represented by a file descriptor managed by redox-rt. Crucially, the kernel’s involvement is minimized; it simply dispatches system calls based on the directory file descriptor (dir_fd) without needing to parse paths. This reduction in kernel complexity is a key benefit of the redesign.

The transition is facilitated by the use of the `openat` system call. With `openat`, the directory file descriptor effectively creates a sandbox, limiting a program’s access to files and directories beneath that directory. This allows for granular control and prevents programs from escaping their designated environments.

The namespace manager’s operation is outlined sequentially: an application calls `open("/home/user/some_file")`. relibc converts this to a scheme-rooted path, calls `openat` using the process’s namespace file descriptor (the `dir_fd`), the nsmgr extracts the target scheme name (file), checks if it's registered in the namespace, and routes the request accordingly. The file scheme then sends a file descriptor to nsmgr, which forwards it to the application.

A key element is the restructuring of the CWD. Previously, relibc treated the CWD as a string, converting all relative paths to absolute paths by joining them with this string. This is now handled differently. relibc now holds the CWD as a file descriptor, eliminating the need for string conversions and enabling the implementation of features like `O_RESOLVE_BENEATH`.

The nsmgr's role is further simplified because it does not need to participate in subsequent file descriptor operations.

The benefits of this approach are significant: a simpler kernel, reduced attack surface, improved stability, and the ability to support more robust sandboxing features via manipulation of the CWD file descriptor. This transformation lays the foundation for future sandboxing capabilities in Redox OS, aligning with the overall move toward capability-based security. The use of the CWD file descriptor effectively becomes a powerful mechanism for controlling program access and preventing escapes, particularly when combined with namespace restrictions. The caching of the CWD path string by relibc for the `getcwd()` function remains, but this could be modified in the future to further enhance sandboxing.

Ultimately, this redesign demonstrates a critical step toward a more secure and robust Redox OS.