Seccomp is a linux kernel feature by Andrea Arcangeli which limits the system calls which a task can use, by allowing a task to say “from now on, msyelf and my new children should not be able to do anything but compute, and read and write to already-open files (and return and exit).” The intent was to allow untrusted guests to use your cpu resources without them being able to abuse any other resources.
Years later, Will Drewry extended the seccomp idea by adding a new mode, typically called seccomp2. He had the brilliant idea to use a BPF (berkeley packet filter) compiler to allow clients to more flexibly define the constraints to be applied. He also managed to support many use cases by providing options for what to do on a denied action. The offending task can be killed; or the system call can be made to return a specified error code (i.e. ENOSYS). Or it can be traced.
In order to make seccomp2 easier to use, libseccomp was introduced. Over the next few weeks I want to add seccomp2 support to lxc containers. So I thought I’d first try a simple test program using libseccomp. Here is the program I used:
#include <stdio.h>
#include <stdlib.h>
#include <seccomp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
FILE *f1;
int fd;
int ret;
f1 = fopen("/tmp/test1", "w");
ret = seccomp_init(SCMP_ACT_ERRNO(5));
if (ret < 0)
printf("Error from seccomp_init\n");
ret = seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
if (!ret)
ret = seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(dup), 0);
if (!ret)
ret = seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
if (!ret)
ret = seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
if (!ret)
ret = seccomp_load();
if (ret)
printf("error setting seccomp\n");
fprintf(f1, "hi there\n");
fd = open("/tmp/test2", O_RDWR);
if (fd >= 0)
printf("error, was able to open f2\n");
else
fprintf(f1, "open returned %d errno %d\n", fd, errno);
fclose(f1);
exit(0);
}
I installed libseccomp-dev, compiled the program, and executed it using
sudo apt-get -y install libseccomp-dev gcc -o seccomp1 seccomp1.c -lseccomp ./seccomp1
The program opens /tmp/test1 for writing. Then it loads a seccomp policy to allow it to only write to files, close files, and exit. It then writes to the open file (allowed), opens a new file (not allowed), and writes the errno it received to the already open file. I told seccomp_init() to give us errno 5, so if you run the program you can check the output in /tmp/test1 to verify that -5 is what you got. If I had called seccomp_init() with the SCMP_KILL argument, then the program would have exited at the open() call, and the last line in the output file would not have been written. You can get much fancier by having the kernel the offending program a SIGSYS and rewinding its execution, or notifying a tracer.
Neat!
Have you tried the sourcecode language=”C” tag for posting source code?
No I haven’t, will try it next time – thanks.