Google Summer of Code 2025 Reports: Using bubblewrap to add sandboxing to NetBSD


November 08, 2025 posted by Leonardo Taccari

This report was written by Vasyl Lanko as part of Google Summer of Code 2025.

Introduction

As of the time of writing, there is no real sandboxing technique available to NetBSD. There is chroot, which can be considered a weak sandbox because it modifies the root directory of the process, effectively restricting the process' view of the file system, but it doesn't isolate anything else, so all networking, IPC, and mounts inside this restricted file system are the same as of the system, and are accessible.

There has already been some research on implementing kernel-level isolation in NetBSD with tools like gaols, mult and netbsd-sandbox, but they haven't been merged to NetBSD. Other operating systems have their own ways to isolate programs, FreeBSD has jails, and Linux has namespaces.

Project Goals

The goal of this project is to bring a new way of sandboxing to NetBSD. More specifically, we want to implement a mechanism like Linux namespaces. These namespaces allow the isolation of parts of the system from a namespace, or, as the user sees it, from an application.

NetBSD has compat_linux to run Linux binaries on NetBSD systems, and the implementation of namespaces can also be utilized to emulate namespace-related functionality of Linux binaries.

A simple example to visualize our intended result is to consider an application running under an isolated UTS namespace that modifies the hostname. From the system's view, the hostname remains the same old hostname, but from the application's view it sees the modified hostname.

Project Implementation

Linux has 8 namespace types, in this project we will focus on only 2 of them:

  • UTS namespace, it is the simplest so we can focus on building the general namespace infrastructure with little namespace-specific details
  • mount namespace, it is a prerequisite to most other namespace types because UNIX follows the philosophy of "everything is a file", so we need a separate mount namespace to have different configuration files on the same location as the system.

Linux creates namespaces via the unshare or clone system calls, and it will also be our way of calling the namespace creation logic.

We setup the base for implementing Linux namespaces in the NetBSD kernel using kauth, the subsystem managing all authorization requests inside the kernel. It associates credentials with objects, and because the namespace lifecycle management is related to the credential lifecycle it handles all the credential inheritance and reference counting for us. (Thanks kauth devs!)

We separate the implementation of each namespace in a different secmodel, resulting in a similar framework to Linux which allows the isolation of a single namespace type. Our implementation also allows users to pick whether they want to have namespace support, and of what kind, via compilation flags, just like in Linux.

UTS namespace

UTS stands for UNIX Timesharing System, because it allows multiple users to share a single computer system. Isolating the utsname can be useful to give users the illusion that they have control over the system's hostname, and also, for example, to give different hostnames to virtual servers.

The UTS namespace stores the namespace's hostname, domain name, and their lengths. To isolate the utsname we need to first create a copy of the current UTS information, plus we need a variable containing the number of credentials referencing this namespace, or, in simpler terms, the reference count of this namespace.

This namespace specific information needs to be saved somewhere, and for that we use the credential's private_data field, so we can use a UTS_key to save and retrieve UTS related information from the secmodel. The key specifies the type of information we want to retrieve from the private_data, hence using a UTS_key for the UTS namespace. The key for each namespace is a fixed value (we don't create a new key for every credential), but the retrieved value for that key from different credentials may be different.

We had to modify kernel code that was directly accessing the hostname and domainname variables, to instead call get_uts(), which retrieves the UTS struct for the namespace of the calling process. We didn't modify occurrences in kernel drivers because drivers are not part of any namespace, so they should still access the system's resources directly.

MNT namespace

The MNT namespace isolates mounts across namespaces. It is used to have different versions of mounted filesystems across namespaces, meaning a user inside a mount namespace can mount and unmount whatever they want without affecting or even breaking the system.

The mount namespace structure in Linux is fairly complicated. To have something similar in NetBSD we need to be able to control the mounts accessed by each namespace, and for that we need to control what is each namespace's mountlist, this is also enough for unmounting file systems, because in practice we can just hide them.

For the mount_namespace, mountlist structure and the number of credentials using the mount namespace are stored in the credential's private data with the MNT_key. Similarly to the UTS namespace, we had to modify kernel code to not directly access the mountlist, but instead go through a wrapper called get_mountlist() which returns the correct mountlist for the namespace the calling process resides in.

Implementation for the mount namespace is immensely more complex than for the UTS namespace, it involves having a good understanding of both Linux and NetBSD behaviour, and I would frequently find myself wondering how to implement something after reading the Linux man pages, which would lead to me looking for it in the Linux source code, understanding it, then going back to NetBSD source code, trying to implement it, and seeing it's too different to implement in the same way.

Project Status

You can find all code written during this project in GitHub at maksymlanko/netbsd-src gsoc-bubblewrap branch. Because I intend to continue this work outside of GSoC, I want to reinforce that this was the last commit still during GSoC on gsoc-bubblewrap branch and this was the last one for the mnt_ns still WIP branch.

The link includes implementation of general namespace code via secmodels, implementation of the UTS namespace and related ATF-tests, and the work-in-progress implementation of mount namespaces.

The mount namespace functionality is not finished as it would require much more work than the time available for this project. To complete it, it would be required invasive and non-trivial changes to the original source code, and, of course, more time.

Future Work

As previously mentioned, Linux has 8 namespace types, it is important to see which of the missing namespaces are considered useful and feasible to implement.

I believe that after mount namespaces it would be interesting to implement PID namespaces as this in combination with mount namespaces would permit process isolation from this sandbox. Afterwards, implementing user namespaces would allow users to get capabilities similar to root in the namespace, giving them sudo permissions while still restricting system-wide actions like shutting down the machine.

A lower hanging fruit is to implement the namespace management functionality, which in Linux is lsns to list existing namespaces, and setns to move the current process to an already existing namespace.

Challenges

  • Semantics. Did you know the unmount system call with MNT_FORCE flag in Linux (usually) returns EBUSY, and in NetBSD it forces the unmounting? One of them makes it easier to implement mount namespaces.
  • The behaviour of namespaces is not fully specified in the man pages. If something is not clear from the man pages you need to read the source code.
  • Unexpected need to learn a lot of VFS concepts and their differences in NetBSD and Linux.
  • There was a much bigger research component than I anticipated.

In the end, Linux and NetBSD are different operating systems, implemented in different ways. Linux is complex and it is not trivial to port namespaces to NetBSD.

Notes

The project is called "Using bubblewrap to add sandboxing to NetBSD" and was initially projected to emulate the unshare system call into compat_linux, but, seeing that having namespaces could be useful for NetBSD, and that it would be easy to add to compat_linux afterwards, we decided to instead implement namespaces directly in the NetBSD kernel. Implementing other system calls necessary to make the bwrap linux binary work correctly also wouldn't be as satisfying as implementing namespaces directly into NetBSD, so this was why the project was initially called "Using bubblewrap to add sandboxing to NetBSD" but nowadays it would be more accurate to call it "Sandboxing in NetBSD with Linux-like namespaces".

Thanks

I am very grateful to Google for Google Summer of Code, because without it I wouldn't have learned so much this summer, wouldn't have met with smart and interesting people, and for sure wouldn't have tried to contribute to a project like NetBSD, even if I always wanted to write operating systems code... But, the biggest thing I will take with me from this project is the confidence to be able to contribute to NetBSD and other open source projects.

I would also like to thank the members of the NetBSD organization for helping me throughout this project, and more specifically:

  • Taylor R. Campbell, Harold Gutch and Nia Alarie from IRC, for helping me fix a nasty LD_LIBRARY_PATH bug I had on my system which wouldn't let me finish compiling NetBSD, and general GSoC recomendations.
  • Emmanuel Dreyfus from tech-kern, with whom I discussed ideas for projects and proposal suggestions, and in the end inspired the namespaces project.
  • Christoph Badura and Leonardo Taccari who volunteered to be my mentors. They took time to research and answer my questions, anticipated possible problems in my approaches, and always pointed me in the right direction, daily, during all of GSoC's period. This project is from the 3 of us.
[0 comments]

 



Post a Comment:
  • HTML Syntax: NOT allowed