kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

seccomp.h (6260B)



      1 /*
      2  * Copyright (c) 2019-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #ifndef __H_SECCOMP_H
     18 #define __H_SECCOMP_H
     19 
     20 #include <sys/syscall.h>
     21 
     22 #include <linux/audit.h>
     23 #include <linux/filter.h>
     24 #include <linux/seccomp.h>
     25 
     26 #include <stddef.h>
     27 
     28 #if __BYTE_ORDER == __LITTLE_ENDIAN
     29 #define ARGS_LO_OFFSET		0
     30 #define ARGS_HI_OFFSET		sizeof(u_int32_t)
     31 #elif __BYTE_ORDER == __BIG_ENDIAN
     32 #define ARGS_LO_OFFSET		sizeof(u_int32_t)
     33 #define ARGS_HI_OFFSET		0
     34 #else
     35 #error "__BYTE_ORDER unknown"
     36 #endif
     37 
     38 /* Do something with a syscall with a user-supplied action. */
     39 #define KORE_SYSCALL_FILTER(_name, _action)		\
     40     KORE_BPF_CMP(SYS_##_name, 0, 1),			\
     41     KORE_BPF_RET(_action)
     42 
     43 /*
     44  * Check if a system call is called with the supplied value as argument.
     45  *
     46  * This is checked in 2 steps due to args being 64-bit and the accumulator
     47  * only being a 32-bit register.
     48  *
     49  * If true we return the given action, otherwise nothing happens.
     50  */
     51 #define KORE_SYSCALL_ARG(_name, _arg, _val, _action)	\
     52     KORE_BPF_CMP(SYS_##_name, 0, 6),			\
     53     KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET),	\
     54     KORE_BPF_CMP(((_val) & 0xffffffff), 0, 3),		\
     55     KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET),	\
     56     KORE_BPF_CMP((((uint32_t)((uint64_t)(_val) >> 32)) & 0xffffffff), 0, 1),  \
     57     KORE_BPF_RET(_action),				\
     58     KORE_BPF_LOAD(nr, 0)
     59 
     60 /*
     61  * Check if a system call is called with the supplied mask as argument.
     62  *
     63  * As KORE_SYSCALL_ARG() this is done in 2 steps.
     64  */
     65 #define KORE_SYSCALL_MASK(_name, _arg, _mask, _action)	\
     66     KORE_BPF_CMP(SYS_##_name, 0, 8),			\
     67     KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET),	\
     68     KORE_BPF_AND(~((_mask) & 0xffffffff)),		\
     69     KORE_BPF_CMP(0, 0, 4),				\
     70     KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET),	\
     71     KORE_BPF_AND(~(((uint32_t)((uint64_t)(_mask) >> 32)) & 0xffffffff)),  \
     72     KORE_BPF_CMP(0, 0, 1),				\
     73     KORE_BPF_RET(_action),				\
     74     KORE_BPF_LOAD(nr, 0)
     75 
     76 /*
     77  * Check if the system call is called with the given value in the argument
     78  * contains the given flag.
     79  */
     80 #define KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, _action)	\
     81     KORE_BPF_CMP(SYS_##_name, 0, 8),			\
     82     KORE_BPF_LOAD(args[(_arg)], ARGS_LO_OFFSET),	\
     83     KORE_BPF_AND(((_flag) & 0xffffffff)),		\
     84     KORE_BPF_CMP(((_flag) & 0xffffffff), 0, 4),		\
     85     KORE_BPF_LOAD(args[(_arg)], ARGS_HI_OFFSET),	\
     86     KORE_BPF_AND((((uint32_t)((uint64_t)(_flag) >> 32)) & 0xffffffff)),        \
     87     KORE_BPF_CMP((((uint32_t)((uint64_t)(_flag) >> 32)) & 0xffffffff), 0, 1),  \
     88     KORE_BPF_RET(_action),				\
     89     KORE_BPF_LOAD(nr, 0)
     90 
     91 /* Denying of system calls macros (with an errno). */
     92 #define KORE_SYSCALL_DENY(_name, _errno)		\
     93     KORE_SYSCALL_FILTER(_name, SECCOMP_RET_ERRNO|(_errno))
     94 
     95 #define KORE_SYSCALL_DENY_ARG(_name, _arg, _val, _errno)	\
     96     KORE_SYSCALL_ARG(_name, _arg, _val, SECCOMP_RET_ERRNO|(_errno))
     97 
     98 #define KORE_SYSCALL_DENY_MASK(_name, _arg, _val, _errno)	\
     99     KORE_SYSCALL_MASK(_name, _arg, _val, SECCOMP_RET_ERRNO|(_errno))
    100 
    101 #define KORE_SYSCALL_DENY_WITH_FLAG(_name, _arg, _flag, _errno)	\
    102     KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, SECCOMP_RET_ERRNO|(_errno))
    103 
    104 /* Allowing of system call macros. */
    105 #define KORE_SYSCALL_ALLOW(_name)			\
    106     KORE_SYSCALL_FILTER(_name, SECCOMP_RET_ALLOW)
    107 
    108 #define KORE_SYSCALL_ALLOW_LOG(_name)			\
    109     KORE_SYSCALL_FILTER(_name, SECCOMP_RET_LOG)
    110 
    111 #define KORE_SYSCALL_ALLOW_ARG(_name, _arg, _val)	\
    112     KORE_SYSCALL_ARG(_name, _arg, _val, SECCOMP_RET_ALLOW)
    113 
    114 #define KORE_SYSCALL_ALLOW_MASK(_name, _arg, _mask)	\
    115     KORE_SYSCALL_MASK(_name, _arg, _mask, SECCOMP_RET_ALLOW)
    116 
    117 #define KORE_SYSCALL_ALLOW_WITH_FLAG(_name, _arg, _flag)	\
    118     KORE_SYSCALL_WITH_FLAG(_name, _arg, _flag, SECCOMP_RET_ALLOW)
    119 
    120 /* Load field of seccomp_data into accumulator. */
    121 #define KORE_BPF_LOAD(_field, _off)				\
    122     BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, _field) + _off)
    123 
    124 /* Return a constant from a BPF program. */
    125 #define KORE_BPF_RET(_retval)				\
    126     BPF_STMT(BPF_RET+BPF_K, _retval)
    127 
    128 /* Compare the accumulator against a constant (==). */
    129 #define KORE_BPF_CMP(_k, _jt, _jf)			\
    130     BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, _k, _jt, _jf)
    131 
    132 /* AND operation on the accumulator. */
    133 #define KORE_BPF_AND(_k)				\
    134     BPF_STMT(BPF_ALU+BPF_AND+BPF_K, _k)
    135 
    136 /* The length of a filter. */
    137 #define KORE_FILTER_LEN(x)		(sizeof(x) / sizeof(x[0]))
    138 
    139 /* Used to mark the end of a BPF program. */
    140 #define KORE_BPF_GUARD		{ USHRT_MAX, UCHAR_MAX, UCHAR_MAX, UINT_MAX }
    141 
    142 /*
    143  * Macro for applications to make easily define custom filter.
    144  *
    145  * eg:
    146  * KORE_SECCOMP_FILTER("filter",
    147  *	KORE_SYSCALL_DENY_ERRNO(socket, EACCESS),
    148  *	KORE_SYSCALL_DENY_ERRNO(ioctl, EACCESS),
    149  *	KORE_SYSCALL_ALLOW(poll),
    150  * )
    151  */
    152 #define KORE_SECCOMP_FILTER(name, ...)				\
    153 	struct sock_filter _scfilt[] = {			\
    154 		__VA_ARGS__					\
    155 	};							\
    156 	void							\
    157 	kore_seccomp_hook(void)					\
    158 	{							\
    159 		kore_seccomp_filter(name, _scfilt,		\
    160 		    KORE_FILTER_LEN(_scfilt));			\
    161 	}
    162 
    163 extern int	kore_seccomp_tracing;
    164 
    165 void	kore_seccomp_init(void);
    166 void	kore_seccomp_drop(void);
    167 void	kore_seccomp_enable(void);
    168 void	kore_seccomp_traceme(void);
    169 int	kore_seccomp_trace(pid_t, int);
    170 int	kore_seccomp_syscall_resolve(const char *);
    171 int	kore_seccomp_filter(const char *, void *, size_t);
    172 
    173 const char		*kore_seccomp_syscall_name(long);
    174 struct sock_filter	*kore_seccomp_syscall_filter(const char *, int);
    175 struct sock_filter	*kore_seccomp_syscall_arg(const char *, int, int, int);
    176 struct sock_filter	*kore_seccomp_syscall_flag(const char *, int, int, int);
    177 struct sock_filter	*kore_seccomp_syscall_mask(const char *, int, int, int);
    178 
    179 #endif