#security #seccomp #syscall


Make your code extrasafe by preventing it from calling unneeded syscalls

5 releases

0.2.0 Sep 1, 2023
0.1.4 Jun 17, 2023
0.1.2 Mar 2, 2022
0.1.1 Mar 2, 2022
0.1.0 Mar 2, 2022

#128 in Unix APIs

Download history 8/week @ 2023-06-07 49/week @ 2023-06-14 36/week @ 2023-06-21 14/week @ 2023-06-28 57/week @ 2023-07-05 6/week @ 2023-07-12 14/week @ 2023-07-19 16/week @ 2023-07-26 6/week @ 2023-08-02 13/week @ 2023-08-09 13/week @ 2023-08-16 18/week @ 2023-08-23 35/week @ 2023-08-30 21/week @ 2023-09-06 8/week @ 2023-09-13 14/week @ 2023-09-20

88 downloads per month
Used in zuk

MIT license

668 lines


Coverage Status CI Status crates.io docs.rs

"trust noone not even urself" - internet man

fn main() {
    println!("disabling syscalls...");


    // Opening files now fails!
    let res = File::create("should_fail.txt");

    println!("but printing to stdout still works!");
    eprintln!("and so does stderr!");

You've used safe and unsafe Rust: now your code can be extrasafe.

extrasafe is a wrapper around libseccomp, which uses the Linux kernel's seccomp syscall-filtering functionality to prevent your program from calling syscalls you don't need. Seccomp is used by systemd, Chrome, application sandboxes like bubblewrap and firejail, and container runtimes. Seccomp by itself is not a complete sandboxing system.

The goal of extrasafe is to make it easy to add extra security to your own programs without having to rely on external configuration by the person running the software.

seccomp is very mildly complicated, so we provide simple defaults that make it hard to misuse: Deny-by-default with pre-selected sets of syscalls to enable.

Additionally, we support slightly advanced use-cases:

  • Allow read/write on only stdin/out/err
  • Allow read/write on specific files (opened before loading the seccomp filters)
  • You can define your own set of syscalls to allow by implementing the RuleSet trait.

Check out the user guide here

Who is extrasafe for?

Application developers who want to tightly control what their programs can and cannot do.

If you're developing a library, there are three things you can do:

  1. Provide an extrasafe::RuleSet that covers the functionality of your library
  2. Provide some kind of init function that does any IO-related work ahead of time (e.g. reading config files, SSL certificates)
  3. If your library has any kind of independent worker threads, you can use extrasafe inside the worker thread.

You don't want to use extrasafe directly in your library because you don't know what other functionality your dependents will be using.

Currently extrasafe only supports x86_64. If you'd like to help support other archs please open an issue.

Other uses

You may be able to use extrasafe to help test certain edge-cases, like the network being unavailable or not being able to read files, but I think that use-case would be better served by a separate library. Email me if you're interested in this!


So you can be extra safe. Suppose your program has a dependency with an undiscovered RCE lurking somewhere: extrasafe allows you to partially hedge against that by disabling access to functionality you don't need.

Specific examples of vulnerabilities that could avoid exploitation with seccomp (looking for contributions!)


Seccomp filters are a somewhat blunt tool.

  • They don't allow you to filter by path name in open calls, or indeed any syscall arguments that are pointers (but see below about Landlock!)
    • In particular, this can make SSL somewhat annoying because you have to open a bunch of files to check for certificates.
  • Their smallest unit of scope is a thread, so if you want to protect possibly risky parsing code in a hot inner loop, you may need to figure out a way to pass data back and forth quickly to an existing thread, rather than spinning up a new thread each time.

Why not X?

Why not both? Keep reading.

Why not use systemd's built-in seccomp support?

systemd supports filtering child processes' syscalls with seccomp via the SystemCallFilter attribute. See e.g. this blog post and the systemd documentation


  • Systemd-specific
  • Precludes writing a backend for e.g. BSD that uses pledge
  • Not as fine-grained:
    • extrasafe lets you open files and then close off further access, for example.
    • extrasafe lets you use the seccomp syscall argument filtering functionality, allowing you to only accept connections on specific, pre-allocated socket fds, for example.
  • By putting the security profile inside your code, it gets to benefit from all of the work and processes put into maintaining codebases: source control, automated testing, code coverage, so you can be sure that your security profile is as specified whenever and wherever your code is deployed.

To those sysadmins or devops reading this and saying "but I don't want to trust that the developers wrote their seccomp filter correctly!" - great! Defense in depth is the goal, and you can and should continue to use AppArmor or your preferred choice of external security control system.

So what about AppArmor or SELinux?

As mentioned above, you should continue to use Linux Security Modules like AppArmor and SELinux! Not every program will be using extrasafe.

In the same way, from the perspective of a developer, there's no guarantee that the person running your code is using them. When there's a bug in your open-source code running on thousands of machines outside of your control, it's much nicer to know that it's not easily exploitable and can be fixed at your leisure, rather than having to coordinate a massive patch-and-upgrade effort to secure the systems.


Landlock is a new LSM that exposes an ABI via new syscalls for userland developers to use, which mitigates the issues described above with regards to filtering on specific filesystem paths.

However, it's very new so older systems very likely don't have access to it, and it also only currently supports filesystem-related functionality.

It does seem to be the way forward in the future.


Using make as a simple command runner until just is packaged for Ubuntu/Debian, or you can run the cargo commands directly.


make test

Lint / clippy

make lint

Code coverage

make coverage


~20K SLoC