安全计算模式 seccomp_rule_add使用文档
名称
seccomp_rule_add, seccomp_rule_add_exact - Add a seccomp filter rule
简介
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <seccomp.h>
typedef void * scmp_filter_ctx;
int SCMP_SYS(syscall_name);
struct scmp_arg_cmp SCMP_CMP(unsigned int arg, enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A0(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A1(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A2(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A3(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A4(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A5(enum scmp_compare op, ...);
struct scmp_arg_cmp SCMP_CMP64(unsigned int arg, enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A0_64(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A1_64(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A2_64(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A3_64(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A4_64(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A5_64(enum scmp_compare op, ...);
struct scmp_arg_cmp SCMP_CMP32(unsigned int arg, enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A0_32(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A1_32(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A2_32(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A3_32(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A4_32(enum scmp_compare op, ...); struct scmp_arg_cmp SCMP_A5_32(enum scmp_compare op, ...);
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...); int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...);
int seccomp_rule_add_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array); int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array);
Link with -lseccomp.
|
描述
1 2 3 4
| seccomp_rule_add(), seccomp_rule_add_array(), seccomp_rule_add_exact(), seccomp_rule_add_exact_array()
|
这四个函数都会向当前seccomp过滤器添加新的过滤规则。
seccomp_rule_add()
和 seccomp_rule_add_array()
这两个函数会“尽最大努力”添加指定的规则,但由于体系结构的特殊性,可能会稍微更改规则。(例如:
多路复用系统调用的内部重写,如x86上的socket和ipc函数).seccomp_rule_add_exact()
和 seccomp_rule_add_exact_array()
函数将尝试完全按照指定的方式添加规则,这样它在不同的体系结构上的行为可能会有所不同。虽然seccomp_rule_add()
和seccomp_rule_add_array()
不能保证一个精确的过滤规则集,但是两个函数无论体系结构如何变化,都能保证相同的行为。
在使用seccomp_load(3)将整个过滤器加载到内核中之前,新添加的过滤器规则不会生效。
SCMP_CMP()
, SCMP_CMP64()
, SCMP_A{0-5}()
, 和 SCMP_A{0-5}_64()
等宏会生成一个scmp-arg-cmp
结构,以用于上述函数。 SCMP_CMP()
和 SCMP_CMP64()
两个宏允许调用者指定任意参数以及比较运算符、64位掩码和64位基准值,其中SCMP_A{0-5}() 和 SCMP_A{0-5}_64()宏是特定于某个参数的。
SCMP_CMP32()
和SCMP_A{0-5}_32()
两个宏与上面的变量类似,但它们采用32位掩码和32位基准值。
建议开发人员尽可能避免使用scmp_cmp()
和SCMP_A{0-5}()
宏,并避免使用显式的32位或64位的变体。因为这有助于消除因负基准值而产生的不必要符号扩展而引起的问题。
虽然可以直接使用标准的 __NR_syscall
值指定系统调用值,但是为了确保跨多个体系结构的正确操作,强烈建议使用scmp_sys()
宏。请参阅下面的示例部分。
从Linux v4.8开始,可能需要创建一个系统调用值为-1的规则,以允许跟踪程序跳过一个系统调用;为了创建一个具有系统调用值为 -1 的规则,必须首先设置 SCMP_FLTATR_API_TSKIP
属性。有关更多信息,请参阅seccomp_attr_set(3)。
上下文过滤器 ctx 是调用seccomp_init(3)返回的值。
有效动作值如下:
当线程调用与筛选规则匹配的系统调用时,线程将被终止。
当进程调用与筛选规则匹配的系统调用时,进程将被终止。
当线程调用与筛选规则匹配的系统调用时,线程将会抛出一个SIGSYS信号。
1
| SCMP_ACT_ERRNO(uint16_t errno)
|
当线程调用与筛选规则匹配的系统调用时,它将收到errno的一个返回值。
1
| SCMP_ACT_TRACE(uint16_t msg_num)
|
如果线程正在被跟踪,并且跟踪进程时在对ptrace(2)的调用中指定了PTRACE_O_TRACESECCOMP选项,则将会通过 PTRACE_EVENT_SECCOMP通知跟踪进程,并且可以使用PTRACE_GETEVENTMSG 选项检索msg_num中提供的值。
如果seccomp筛选器与筛选器规则匹配,则它不会对调用系统调用的线程产生任何影响,但系统调用会被记录到日志。
如果seccomp筛选器与筛选器规则匹配,则它不会对调用系统调用的线程产生任何影响。
有效比较操作值如下:
参数值不等于基准值时匹配,例如:
1 2
| SCMP_CMP( arg , SCMP_CMP_NE , datum ) SCMP_CMP_LT
|
参数值小于基准值时匹配,例如:
1 2
| SCMP_CMP( arg , SCMP_CMP_LT , datum ) SCMP_CMP_LE
|
参数值小于或等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_LE , datum )
参数值等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_EQ , datum )
参数值大于或等于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_GE , datum )
参数值大于基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_GT , datum )
当掩码参数值等于掩码基准值时匹配,例如:
SCMP_CMP( arg , SCMP_CMP_MASKED_EQ , mask , datum )
返回值
seccomp_rule_add()
, seccomp_rule_add_array()
, seccomp_rule_add_exact()
, 和seccomp_rule_add_exact_array()
函数成功时返回零,失败时返回负的errno值。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <fcntl.h> #include <seccomp.h> #include <sys/stat.h> #include <sys/types.h> #include <stddef.h>
#define BUF_SIZE 256
int main(int argc, char *argv[]) { int rc = -1; scmp_filter_ctx ctx; struct scmp_arg_cmp arg_cmp[] = { SCMP_A0(SCMP_CMP_EQ, 2) }; int fd; unsigned char buf[BUF_SIZE];
ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) goto out;
fd = open("file.txt", 0);
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc < 0) goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); if (rc < 0) goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); if (rc < 0) goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3, SCMP_A0(SCMP_CMP_EQ, fd), SCMP_A1(SCMP_CMP_EQ, (scmp_datum_t)buf), SCMP_A2(SCMP_CMP_LE, BUF_SIZE)); if (rc < 0) goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_CMP(0, SCMP_CMP_EQ, fd)); if (rc < 0) goto out;
rc = seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, arg_cmp); if (rc < 0) goto out;
rc = seccomp_load(ctx); if (rc < 0) goto out;
out: seccomp_release(ctx); return -rc; }
|
注意
虽然可以独立于内核生成seccomp过滤器,但是需要内核支持来加载和执行libseccomp生成的seccomp过滤器。
libseccomp项目站点(包含更多信息和源代码存储库)位于https://github.com/seccomp/libseccomp。此工具以及libseccomp库目前正在开发中,请在项目站点或直接向作者报告任何错误。
其他参考
seccomp_syscall_resolve_name_rewrite(3), seccomp_syscall_priority(3),
seccomp_load(3), seccomp_attr_set(3)
出处:本文来源