mirror of https://git.kore.io/kore.git
seccomp improvements.
More BPF helper macros, more helper for granular syscall checking. Use these throughout kore where it makes sense. The new helpers: - KORE_SYSCALL_DENY_ARG(name, arg, value, errno): Deny the system call with errno if the argument matches value. - KORE_SYSCALL_DENY_MASK(name, arg, mask, errno): Deny the system call with errno if the mask argument does not match the exact mask given. - KORE_SYSCALL_DENY_WITH_FLAG(name, arg, flag, errno): Deny the system call with errno if the argument contains the given flag. The reverse also exists: - KORE_SYSCALL_ALLOW_ARG() - KORE_SYSCALL_ALLOW_MASK() - KORE_SYSCALL_ALLOW_WITH_FLAG()
This commit is contained in:
parent
4ed6136693
commit
296fe7a6d4
|
@ -23,22 +23,113 @@
|
|||
#include <linux/filter.h>
|
||||
#include <linux/seccomp.h>
|
||||
|
||||
/* Do something with a syscall with a user-supplied action. */
|
||||
#define KORE_SYSCALL_FILTER(_name, _action) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##_name, 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, _action)
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ARGS_LO_OFFSET 0
|
||||
#define ARGS_HI_OFFSET sizeof(u_int32_t)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ARGS_LO_OFFSET sizeof(u_int32_t)
|
||||
#define ARGS_HI_OFFSET 0
|
||||
#else
|
||||
#error "__BYTE_ORDER unknown"
|
||||
#endif
|
||||
|
||||
/* Allow a system call completely. */
|
||||
#define KORE_SYSCALL_ALLOW(_name) \
|
||||
/* Do something with a syscall with a user-supplied action. */
|
||||
#define KORE_SYSCALL_FILTER(_name, _action) \
|
||||
KORE_BPF_CMP(SYS_##_name, 0, 1), \
|
||||
KORE_BPF_RET(_action)
|
||||
|
||||
/*
|
||||
* Check if a system call is called with the supplied value as argument.
|
||||
*
|
||||
* This is checked in 2 steps due to args being 64-bit and the accumulator
|
||||
* only being a 32-bit register.
|
||||
*
|
||||
* If true we return the given action, otherwise nothing happens.
|
||||
*/
|
||||
#define KORE_SYSCALL_ARG(_name, _arg, _val, _action) \
|
||||
KORE_BPF_CMP(SYS_##_name, 0, 6), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET), \
|
||||
KORE_BPF_CMP(((_val) & 0xffffffff), 0, 3), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET), \
|
||||
KORE_BPF_CMP((((uint32_t)((uint64_t)(_val) >> 32)) & 0xffffffff), 0, 1), \
|
||||
KORE_BPF_RET(_action), \
|
||||
KORE_BPF_LOAD(nr, 0)
|
||||
|
||||
/*
|
||||
* Check if a system call is called with the supplied mask as argument.
|
||||
*
|
||||
* As KORE_SYSCALL_ARG() this is done in 2 steps.
|
||||
*/
|
||||
#define KORE_SYSCALL_MASK(_name, _arg, _mask, _action) \
|
||||
KORE_BPF_CMP(SYS_##_name, 0, 8), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET), \
|
||||
KORE_BPF_AND(~((_mask) & 0xffffffff)), \
|
||||
KORE_BPF_CMP(0, 0, 4), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET), \
|
||||
KORE_BPF_AND(~(((uint32_t)((uint64_t)(_mask) >> 32)) & 0xffffffff)), \
|
||||
KORE_BPF_CMP(0, 0, 1), \
|
||||
KORE_BPF_RET(_action), \
|
||||
KORE_BPF_LOAD(nr, 0)
|
||||
|
||||
/*
|
||||
* Check if the system call is called with the given value in the argument
|
||||
* contains the given flag.
|
||||
*/
|
||||
#define KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, _action) \
|
||||
KORE_BPF_CMP(SYS_##_name, 0, 8), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET), \
|
||||
KORE_BPF_AND(((_flag) & 0xffffffff)), \
|
||||
KORE_BPF_CMP(((_flag) & 0xffffffff), 0, 4), \
|
||||
KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET), \
|
||||
KORE_BPF_AND((((uint32_t)((uint64_t)(_flag) >> 32)) & 0xffffffff)), \
|
||||
KORE_BPF_CMP((((uint32_t)((uint64_t)(_flag) >> 32)) & 0xffffffff), 0, 1), \
|
||||
KORE_BPF_RET(_action), \
|
||||
KORE_BPF_LOAD(nr, 0)
|
||||
|
||||
/* Denying of system calls macros (with an errno). */
|
||||
#define KORE_SYSCALL_DENY(_name, _errno) \
|
||||
KORE_SYSCALL_FILTER(_name, SECCOMP_RET_ERRNO|(_errno))
|
||||
|
||||
#define KORE_SYSCALL_DENY_ARG(_name, _arg, _val, _errno) \
|
||||
KORE_SYSCALL_ARG(_name, _arg, _val, SECCOMP_RET_ERRNO|(_errno))
|
||||
|
||||
#define KORE_SYSCALL_DENY_MASK(_name, _arg, _val, _errno) \
|
||||
KORE_SYSCALL_MASK(_name, _arg, _val, SECCOMP_RET_ERRNO|(_errno))
|
||||
|
||||
#define KORE_SYSCALL_DENY_WITH_FLAG(_name, _arg, _flag, _errno) \
|
||||
KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, SECCOMP_RET_ERRNO|(_errno))
|
||||
|
||||
/* Allowing of system call macros. */
|
||||
#define KORE_SYSCALL_ALLOW(_name) \
|
||||
KORE_SYSCALL_FILTER(_name, SECCOMP_RET_ALLOW)
|
||||
|
||||
/* Allow system call, but log it. */
|
||||
#define KORE_SYSCALL_ALLOW_LOG(_name) \
|
||||
#define KORE_SYSCALL_ALLOW_LOG(_name) \
|
||||
KORE_SYSCALL_FILTER(_name, SECCOMP_RET_LOG)
|
||||
|
||||
/* Explicit deny of a system call with an errno code for the caller. */
|
||||
#define KORE_SYSCALL_DENY_ERRNO(_name, _errno) \
|
||||
KORE_SYSCALL_FILTER(_name, SECCOMP_RET_ERRNO|(_errno))
|
||||
#define KORE_SYSCALL_ALLOW_ARG(_name, _arg, _val) \
|
||||
KORE_SYSCALL_ARG(_name, _arg, _val, SECCOMP_RET_ALLOW)
|
||||
|
||||
#define KORE_SYSCALL_ALLOW_MASK(_name, _arg, _mask) \
|
||||
KORE_SYSCALL_MASK(_name, _arg, _mask, SECCOMP_RET_ALLOW)
|
||||
|
||||
#define KORE_SYSCALL_ALLOW_WITH_FLAG(_name, _arg, _flag) \
|
||||
KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, SECCOMP_RET_ALLOW)
|
||||
|
||||
/* Load field of seccomp_data into accumulator. */
|
||||
#define KORE_BPF_LOAD(_field, _off) \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, _field) + _off)
|
||||
|
||||
/* Return a constant from a BPF program. */
|
||||
#define KORE_BPF_RET(_retval) \
|
||||
BPF_STMT(BPF_RET+BPF_K, _retval)
|
||||
|
||||
/* Compare the accumulator against a constant (==). */
|
||||
#define KORE_BPF_CMP(_k, _jt, _jf) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, _k, _jt, _jf)
|
||||
|
||||
/* AND operation on the accumulator. */
|
||||
#define KORE_BPF_AND(_k) \
|
||||
BPF_STMT(BPF_ALU+BPF_AND+BPF_K, _k)
|
||||
|
||||
/* The length of a filter. */
|
||||
#define KORE_FILTER_LEN(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
@ -52,7 +143,6 @@
|
|||
* KORE_SYSCALL_DENY_ERRNO(ioctl, EACCESS),
|
||||
* KORE_SYSCALL_ALLOW(poll),
|
||||
* );
|
||||
*
|
||||
*/
|
||||
#define KORE_SECCOMP_FILTER(name, ...) \
|
||||
struct sock_filter _scfilt[] = { \
|
||||
|
|
|
@ -28,8 +28,10 @@
|
|||
static struct sock_filter filter_curl[] = {
|
||||
/* Allow sockets and libcurl to call connect. */
|
||||
KORE_SYSCALL_ALLOW(bind),
|
||||
KORE_SYSCALL_ALLOW(socket),
|
||||
KORE_SYSCALL_ALLOW(connect),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX),
|
||||
|
||||
/* Threading related. */
|
||||
KORE_SYSCALL_ALLOW(clone),
|
||||
|
|
|
@ -32,10 +32,13 @@
|
|||
#include "seccomp.h"
|
||||
|
||||
static struct sock_filter filter_pgsql[] = {
|
||||
KORE_SYSCALL_ALLOW(socket),
|
||||
/* Allow us to create sockets and call connect. */
|
||||
KORE_SYSCALL_ALLOW(connect),
|
||||
KORE_SYSCALL_ALLOW(sendto),
|
||||
KORE_SYSCALL_ALLOW(recvfrom),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6),
|
||||
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX),
|
||||
|
||||
/* Requires these calls. */
|
||||
KORE_SYSCALL_ALLOW(getsockopt),
|
||||
KORE_SYSCALL_ALLOW(getsockname),
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
|
@ -42,7 +43,7 @@
|
|||
*/
|
||||
static struct sock_filter filter_kore[] = {
|
||||
/* Deny these, but with EACCESS instead of dying. */
|
||||
KORE_SYSCALL_DENY_ERRNO(ioctl, EACCES),
|
||||
KORE_SYSCALL_DENY(ioctl, EACCES),
|
||||
|
||||
/* File related. */
|
||||
KORE_SYSCALL_ALLOW(open),
|
||||
|
@ -54,10 +55,10 @@ static struct sock_filter filter_kore[] = {
|
|||
KORE_SYSCALL_ALLOW(fcntl),
|
||||
KORE_SYSCALL_ALLOW(lseek),
|
||||
KORE_SYSCALL_ALLOW(close),
|
||||
KORE_SYSCALL_ALLOW(openat),
|
||||
KORE_SYSCALL_ALLOW(access),
|
||||
KORE_SYSCALL_ALLOW(writev),
|
||||
KORE_SYSCALL_ALLOW(getcwd),
|
||||
KORE_SYSCALL_ALLOW(openat),
|
||||
KORE_SYSCALL_ALLOW(unlink),
|
||||
|
||||
/* Process related. */
|
||||
|
@ -70,8 +71,13 @@ static struct sock_filter filter_kore[] = {
|
|||
|
||||
/* Memory related. */
|
||||
KORE_SYSCALL_ALLOW(brk),
|
||||
KORE_SYSCALL_ALLOW(mmap),
|
||||
KORE_SYSCALL_ALLOW(munmap),
|
||||
|
||||
/* Deny mmap/mprotect calls with PROT_EXEC/PROT_WRITE protection. */
|
||||
KORE_SYSCALL_DENY_WITH_FLAG(mmap, 2, PROT_EXEC | PROT_WRITE, EINVAL),
|
||||
KORE_SYSCALL_DENY_WITH_FLAG(mprotect, 2, PROT_EXEC, EINVAL),
|
||||
|
||||
KORE_SYSCALL_ALLOW(mmap),
|
||||
KORE_SYSCALL_ALLOW(mprotect),
|
||||
|
||||
/* Net related. */
|
||||
|
@ -103,14 +109,14 @@ static struct sock_filter filter_kore[] = {
|
|||
/* bpf program prologue. */
|
||||
static struct sock_filter filter_prologue[] = {
|
||||
/* Load arch member into accumulator (A) (arch is __u32). */
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, arch)),
|
||||
KORE_BPF_LOAD(arch, 0),
|
||||
|
||||
/* Compare accumulator against constant, if false jump over kill. */
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0),
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
|
||||
KORE_BPF_CMP(SECCOMP_AUDIT_ARCH, 1, 0),
|
||||
KORE_BPF_RET(SECCOMP_RET_KILL),
|
||||
|
||||
/* Load system call member into accumulator (nr is int). */
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),
|
||||
/* Load the system call number into the accumulator. */
|
||||
KORE_BPF_LOAD(nr, 0),
|
||||
};
|
||||
|
||||
/* bpf program epilogue. */
|
||||
|
|
Loading…
Reference in New Issue