1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <assert.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <sched.h>
9
10#include <sys/types.h>
11#include <sys/socket.h>
12#include <sys/syscall.h>
13
14static int exit_code = 0;
15
16/*
17 * We need raw wrappers around each syscall so that glibc won't rewrite the
18 * errno value when it is returned from the seccomp filter (glibc has a habit
19 * of hiding -ENOSYS if possible -- which counters what we're trying to test).
20 */
21#define raw(name, ...) \
22 syscall(SYS_ ## name, ##__VA_ARGS__)
23
24#define syscall_assert(sval, rval) \
25 do { \
26 int L = (sval), R = (rval); \
27 if (L < 0) \
28 L = -errno; \
29 if (L != R) { \
30 printf("syscall_assert(%s == %s) failed: %d != %d\n", #sval, #rval, L, R); \
31 exit_code = 32; \
32 } \
33 } while (0)
34
35int main(void)
36{
37 // Basic permitted syscalls.
38 syscall_assert(write(-1, NULL, 0), -EBADF);
39
40 // Basic syscall with masked rules.
41 syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x000), 3);
42 syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x0FF), -EPROTONOSUPPORT);
43 syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x001), 4);
44 syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0x100), -EPERM);
45 syscall_assert(raw(socket, AF_UNIX, SOCK_STREAM, 0xC00), -EPERM);
46
47 // Multiple arguments with OR rules.
48 syscall_assert(raw(process_vm_readv, 100, NULL, 0, NULL, 0, ~0), -EINVAL);
49 syscall_assert(raw(process_vm_readv, 9001, NULL, 0, NULL, 0, ~0), -EINVAL);
50 syscall_assert(raw(process_vm_readv, 0, NULL, 0, NULL, 0, ~0), -EPERM);
51 syscall_assert(raw(process_vm_readv, 0, NULL, 0, NULL, 0, ~0), -EPERM);
52
53 // Multiple arguments with OR rules -- rule is ERRNO(-ENOANO).
54 syscall_assert(raw(process_vm_writev, 1337, NULL, 0, NULL, 0, ~0), -ENOANO);
55 syscall_assert(raw(process_vm_writev, 2020, NULL, 0, NULL, 0, ~0), -ENOANO);
56 syscall_assert(raw(process_vm_writev, 0, NULL, 0, NULL, 0, ~0), -EPERM);
57 syscall_assert(raw(process_vm_writev, 0, NULL, 0, NULL, 0, ~0), -EPERM);
58
59 // Multiple arguments with AND rules.
60 syscall_assert(raw(kcmp, 0, 1337, 0, 0, 0), -ESRCH);
61 syscall_assert(raw(kcmp, 0, 0, 0, 0, 0), -EPERM);
62 syscall_assert(raw(kcmp, 500, 1337, 0, 0, 0), -EPERM);
63 syscall_assert(raw(kcmp, 500, 500, 0, 0, 0), -EPERM);
64
65 // Multiple rules for the same syscall.
66 syscall_assert(raw(dup3, 0, -100, 0xFFFF), -EPERM);
67 syscall_assert(raw(dup3, 1, -100, 0xFFFF), -EINVAL);
68 syscall_assert(raw(dup3, 2, -100, 0xFFFF), -EPERM);
69 syscall_assert(raw(dup3, 3, -100, 0xFFFF), -EINVAL);
70
71 // Explicitly denied syscalls (those in Linux 3.0) get -EPERM.
72 syscall_assert(raw(unshare, 0), -EPERM);
73 syscall_assert(raw(setns, 0, 0), -EPERM);
74
75 // Out-of-bounds fake syscall.
76 syscall_assert(syscall(1000, 0xDEADBEEF, 0xCAFEFEED, 0x1337), -ENOSYS);
77
78 return exit_code;
79}
View as plain text