Go Seccomp Filters – Part 1

Estimated reading time: 5 Minutes

In the following two blog posts series you are welcome to deep dive with me into applying seccomp filters on Go applications.

Navigating your way bottom-up, these posts will give you a better understanding of what seccomp is. Hopefully, when finish reading this short, two-parts guide, you’ll be able to use it to protect your Go binary.

If you already know what seccomp filtering is, I suggest you skip to part two.

In order to understand what a seccomp filter is and why should you even want to use it, let’s first start with a definition of another term – system call. Soon enough you’ll understand why.

What is a system call?

Using  Wikipedia’s definition:

In computing, a system call (commonly abbreviated to syscall) is the programmatic way in which a computer program requests a service from the kernel of the operating system on which it is executed.

In other words, a syscall is a way of a process to communicate with the operating system.

Now let’s take a look at the simplest Go application and see syscalls in action.

In order to do that, you will use a tool called strace. strace is a tool that’s used to monitor and tamper with interactions between processes and the Linux kernel. In our case, we will use it to output the syscalls our application is generating.

Install strace with the following commands:

$ sudo apt-get update -y
$ sudo apt-get install -y strace

We can now create the most basic Go application:

package main
import "fmt"
func main() {
    fmt.Printf("### Code The Cloud ###")

Build it’s binary, and run strace to monitor the syscalls it generates:

$ strace -c ./main
### Code The Cloud ###
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0         1           close
  0.00    0.000000           0        19           mmap
  0.00    0.000000           0       114           rt_sigaction
  0.00    0.000000           0        11           rt_sigprocmask
  0.00    0.000000           0         3           clone
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           uname
  0.00    0.000000           0         3           fcntl
  0.00    0.000000           0         8           sigaltstack
  0.00    0.000000           0         4           mlock
  0.00    0.000000           0         4           arch_prctl
  0.00    0.000000           0         7           gettid
  0.00    0.000000           0         4           futex
  0.00    0.000000           0         1           sched_getaffinity
  0.00    0.000000           0         1           openat
  0.00    0.000000           0         1           readlinkat
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                   185           total

Note that the -c flag supplied to strace simply means that strace outputs a report summary.

As you can see, our simple application generates all sorts of syscalls.

Now that you understand what a syscall is, you can continue your journey.

What is seccomp?

Seccomp (short for secure computing mode) is a feature provided by the Linux kernel. It provides the ability to run a process in a limited mode, in which syscalls made by a process are limited to a specific group.

Seccomp has proved as a useful way to minimize the attack surface of applications. The problem was that the limited syscalls group are predefined. It was this shortcoming that lead to the next step of seccomp evolution – seccomp filter.

A seccomp filter (also known as seccomp-bpf) is an extension of seccomp that allows filtering syscalls using a configurable policy. Meaning, you can control exactly which syscalls are allowed or denied.

Why should you use a seccomp filter?

Applying a seccomp filter to your application allows you to get a better security posture. When coding an application, you know exactly which syscalls are expected to be executed. If your application was to be compromised, in most cases, it will generate syscalls that differ from your initial design – and those can get blocked via a seccomp filter.

Let’s look at an actual example:

Say you were coding an executable that is a main process of a container. You plan on deploying this container as part of your production deployment. Generally, your application just creates some files and writes data to them. Assuming this container was compromised. Meaning, your application now does whatever the attacker sees fit. The attacker can now, for example, send out data that your container created.

If you were to apply a seccomp filter, any other operation that does not involve creating and writing files would have been blocked.

In the next post you will protect your Go application by applying seccomp filters to it.

Leave a Reply