Skip to content

Commit

Permalink
tests: add seccomp -ENOSYS integration test
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksa Sarai <[email protected]>
  • Loading branch information
cyphar committed Jan 25, 2021
1 parent 8c6a044 commit 14b3426
Show file tree
Hide file tree
Showing 7 changed files with 570 additions and 2 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ RUN echo 'deb https://download.opensuse.org/repositories/devel:/tools:/criu/Debi
crossbuild-essential-ppc64el \
curl \
gawk \
gcc \
iptables \
jq \
kmod \
Expand Down
2 changes: 1 addition & 1 deletion Vagrantfile.centos7
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Vagrant.configure("2") do |config|
# install yum packages
yum install -y -q epel-release
(cd /etc/yum.repos.d && curl -O https://copr.fedorainfracloud.org/coprs/adrian/criu-el7/repo/epel-7/adrian-criu-el7-epel-7.repo)
yum install -y -q gcc git iptables jq libseccomp-devel make skopeo criu
yum install -y -q gcc git iptables jq glibc-static libseccomp-devel make skopeo criu
yum clean all
# install Go
Expand Down
2 changes: 1 addition & 1 deletion Vagrantfile.fedora33
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Vagrant.configure("2") do |config|
config exclude kernel,kernel-core
config install_weak_deps false
update
install iptables gcc make golang-go libseccomp-devel bats jq git-core criu skopeo
install iptables gcc make golang-go glibc-static libseccomp-devel bats jq git-core criu skopeo
ts run
EOF
done
Expand Down
Empty file removed tests/integration/config.json
Empty file.
24 changes: 24 additions & 0 deletions tests/integration/seccomp.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bats

load helpers

function setup() {
teardown_busybox
setup_busybox
}

function teardown() {
teardown_busybox
}

@test "runc run [seccomp -ENOSYS handling]" {
TEST_NAME="seccomp_syscall_test1"

# Compile the test binary and update the config to run it.
gcc -static -o rootfs/seccomp_test "${TESTDATA}/${TEST_NAME}.c"
update_config ".linux.seccomp = $(<"${TESTDATA}/${TEST_NAME}.json")"
update_config '.process.args = ["/seccomp_test"]'

runc run test_busybox
[ "$status" -eq 0 ]
}
79 changes: 79 additions & 0 deletions tests/integration/testdata/seccomp_syscall_test1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/syscall.h>

static int exit_code = 0;

/*
* We need raw wrappers around each syscall so that glibc won't rewrite the
* errno value when it is returned from the seccomp filter (glibc has a habit
* of hiding -ENOSYS if possible -- which counters what we're trying to test).
*/
#define raw(name, ...) \
syscall(SYS_ ## name, ##__VA_ARGS__)

#define syscall_assert(sval, rval) \
do { \
int L = (sval), R = (rval); \
if (L < 0) \
L = -errno; \
if (L != R) { \
printf("syscall_assert(%s == %s) failed: %d != %d\n", #sval, #rval, L, R); \
exit_code = 32; \
} \
} while (0)

int main(void)
{
// Basic permitted syscalls.
syscall_assert(write(-1, NULL, 0), -EBADF);

// Basic syscall with masked rules.
syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x000), 3);
syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x0FF), -EPROTONOSUPPORT);
syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x001), 4);
syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x100), -EPERM);
syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0xC00), -EPERM);

// Multiple arguments with OR rules.
syscall_assert(raw(process_vm_readv, 100, NULL, 0, NULL, 0, ~0), -EINVAL);
syscall_assert(raw(process_vm_readv, 9001, NULL, 0, NULL, 0, ~0), -EINVAL);
syscall_assert(raw(process_vm_readv, 0, NULL, 0, NULL, 0, ~0), -EPERM);
syscall_assert(raw(process_vm_readv, 0, NULL, 0, NULL, 0, ~0), -EPERM);

// Multiple arguments with OR rules -- rule is ERRNO(-ENOANO).
syscall_assert(raw(process_vm_writev, 1337, NULL, 0, NULL, 0, ~0), -ENOANO);
syscall_assert(raw(process_vm_writev, 2020, NULL, 0, NULL, 0, ~0), -ENOANO);
syscall_assert(raw(process_vm_writev, 0, NULL, 0, NULL, 0, ~0), -EPERM);
syscall_assert(raw(process_vm_writev, 0, NULL, 0, NULL, 0, ~0), -EPERM);

// Multiple arguments with AND rules.
syscall_assert(raw(kcmp, 0, 1337, 0, 0, 0), -ESRCH);
syscall_assert(raw(kcmp, 0, 0, 0, 0, 0), -EPERM);
syscall_assert(raw(kcmp, 500, 1337, 0, 0, 0), -EPERM);
syscall_assert(raw(kcmp, 500, 500, 0, 0, 0), -EPERM);

// Multiple rules for the same syscall.
syscall_assert(raw(dup3, 0, -100, 0xFFFF), -EPERM);
syscall_assert(raw(dup3, 1, -100, 0xFFFF), -EINVAL);
syscall_assert(raw(dup3, 2, -100, 0xFFFF), -EPERM);
syscall_assert(raw(dup3, 3, -100, 0xFFFF), -EINVAL);

// Explicitly denied syscalls (those in Linux 3.0) get -EPERM.
syscall_assert(raw(unshare, 0), -EPERM);
syscall_assert(raw(setns, 0, 0), -EPERM);

// Out-of-bounds fake syscall.
syscall_assert(syscall(1000, 0xDEADBEEF, 0xCAFEFEED, 0x1337), -ENOSYS);

return exit_code;
}
Loading

0 comments on commit 14b3426

Please sign in to comment.