mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 14:13:58 +08:00
053f6a0dca
kcmp is often missing: https://man7.org/linux/man-pages/man2/kcmp.2.html > Before Linux 5.12, this system call is available only if the > kernel is configured with CONFIG_CHECKPOINT_RESTORE, since the > original purpose of the system call was for the > checkpoint/restore in user space (CRIU) feature. (The > alternative to this system call would have been to expose > suitable process information via the proc(5) filesystem; this was > deemed to be unsuitable for security reasons.) Since Linux 5.12, > this system call is also available if the kernel is configured > with CONFIG_KCMP. Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
80 lines
2.7 KiB
C
80 lines
2.7 KiB
C
#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(ftruncate, 123456789, 1337), -EBADF);
|
|
syscall_assert(raw(ftruncate, 123456789, 0), -EPERM);
|
|
syscall_assert(raw(ftruncate, 500, 1337), -EPERM);
|
|
syscall_assert(raw(ftruncate, 500, 500), -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;
|
|
}
|