Sandboxing with Firejail

This article brought to you by LWN subscribers Subscribers to LWN.net made this article — and everything that surrounds it — possible. If you appreciate our content, please buy a subscription and make the next set of articles possible.

The idea of sandboxing applications has a certain appeal. By restricting a program's access to various features and parts of the system that it shouldn't need, any harm that can come from a compromise can be reduced—often, substantially so. But putting together the required pieces for a given application is a tedious task, which is part of why projects like Firejail have been started. Firejail uses namespaces, seccomp BPF, Linux capabilities, and other kernel features to apply restrictions to arbitrary programs, but it also has profiles targeting popular applications.

One of the goals of the project is to make using sandboxes easy or, as the Documentation page puts it: "There is no difficult in Firejail, at least not SELinux-difficult." To that end, running Firefox in a sandbox is done with a simple command:

$ firejail firefox

That command will launch Firefox inside of a sandbox with a whole list of pre-configured restrictions . One can also modify the profile or create a new one with different restrictions.

The firejail command is a setuid-root program that sets up namespaces, seccomp filters, and capabilities before executing the desired program. It is a C program that is available under the GPLv2; it also comes with profiles for more than 30 different applications. There is a Qt-based GUI, called Firetools, available as well.

Simply invoking firejail will start a shell using the generic profile. That profile will remove all capabilities, create a user namespace with only one user (the current user, thus typically no mapping to the root user outside the namespace), disallow any network protocols other than Unix sockets, IPv4, and IPv6 using seccomp, blacklist access to certain files (by mounting empty root-owned files or directories on them), and so on. Profiles can also use the include directive to reference other profiles. So there are some commonly used profiles that are included by the generic profile to restrict access to a large number of home directory files and directories (e.g. .bashrc , .emacs , .ssh ), system files (e.g. /etc/shadow ), and management utilities (e.g. mount , su ). While those lists cannot be exhaustive (especially for various application-specific configuration directories in the home directory), users can add their own entries to the blacklist.

In addition, as described on the Basic Usage page, Firejail can be started with the --private option to replace the user's home directory with an empty one. It does that by mounting a tmpfs atop the home directory; the tmpfs will be destroyed when Firejail exits. Alternatively, users can specify a persistent directory ( --private=~/my_sandbox_dir ) to store sandbox data.

The default behavior for Firejail (when invoked without the generic profile using the --noprofile option) is to create new mount, PID, and UTS namespaces, but it can also be invoked (or configured) to use new network and user namespaces as well. If invoked with --net=eth0 option, for example, the network namespace will use the system's eth0 device with the macvlan driver to create a new network device inside the namespace that can communicate with the outside world. Bridging is also supported. The --net=none option will create a new network namespace without any devices, so processes cannot communicate outside of the namespace.

There is lots more to Firejail; the highlights of its feature set are outlined on the Features page. There is also plenty of documentation, ranging from man pages for firejail and firejail-profile (which describes the configuration options for profiles) to information on building custom profiles and filtering system calls using Firejail and seccomp. It is, in short, a rather comprehensive framework for applying a sandbox to applications.

But it is not only restricted to GUI applications like web browsers, email readers, BitTorrent clients, media players, and the like. It also supports running server processes in sandboxes. This is where capabilities are likely to come more into play. As described on the Linux Capabilities Guide page, programs like web servers and other network services can be restricted to just a handful of capabilities that are needed to do their job (e.g. CAP_NET_BIND_SERVICE , CAP_SETUID ). That will reduce what a compromise of those processes can accomplish (though Linux capabilities are known to have weaknesses).

Over time, the number of profiles available should grow and additions will likely be made to the existing generic profile and the other commonly included profiles. Obviously, getting those profiles "right" is an important piece of the puzzle. For the most part, it is a blacklist approach (though support for using whitelists of files is present), which may allow some important things to be unprotected. That said, it is clearly far better than simply running these applications with all of the access and privileges of the user. Root-level compromises are certainly terrible, but for most regular users, their crown jewels live in their home directory anyway, so a full compromise is not substantially worse.

The idea of Firejail came from the sandbox that Google uses for the rendering processes in its Chrome browser, but it goes much further than that. It uses many of the security and isolation technologies that have been added to the kernel over the last decade or so—including control groups for resource limiting the sandboxes. We have covered many of those technologies over that time, so it is nice to see them being used in ways that can help users protect themselves from attacks of various kinds. The next time you want to run an unknown new program or visit a dodgy web site, Firejail might be a good option to reduce the harm that might otherwise occur.

[ Thanks to Raphaël Rigo for giving us a heads up about Firejail. ]

