seccomp函数用法及示例

seccomp(Secure Computing Mode)是 Linux 内核的安全机制,用于限制进程可用的系统调用(syscall),从而减少攻击面。以下是详细用法和示例:


核心概念

  1. 两种模式

    • SECCOMP_MODE_STRICT:只允许 read, write, _exit, sigreturn 四个系统调用。
    • SECCOMP_MODE_FILTER(推荐):基于 BPF 规则自定义允许/拒绝的系统调用。
  2. 常用工具

    • 系统调用:prctl()seccomp()
    • 库:libseccomp(简化操作,推荐使用)

使用 libseccomp 的步骤

  1. 初始化过滤器
    设置默认动作(如拒绝非法 syscall)。

    1
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); // 非法调用时杀死进程
  2. 添加允许的规则
    明确允许需要的系统调用。

    1
    2
    3
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);     // 允许 read
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // 允许 write
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); // 允许 exit
  3. 加载并应用规则

    1
    seccomp_load(ctx);
  4. 释放资源

    1
    seccomp_release(ctx);

完整示例:限制为只读/写文件

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
#include <seccomp.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main() {
// 初始化过滤器:默认杀死进程
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
if (!ctx) exit(EXIT_FAILURE);

// 允许基础系统调用
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); // 退出进程
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); // 读文件
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // 写文件
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); // 打开文件
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); // 关闭文件

// 加载过滤器
if (seccomp_load(ctx) != 0) {
seccomp_release(ctx);
exit(EXIT_FAILURE);
}

// 测试:写入文件(允许)
int fd = open("test.txt", O_CREAT | O_WRONLY, 0644);
write(fd, "Hello seccomp!", 14);
close(fd);

// 尝试禁止的操作(如 fork())会触发 SIGSYS
// fork(); // 此调用将被阻止,进程被终止

seccomp_release(ctx);
return 0;
}

编译

1
gcc example.c -o example -lseccomp

高级用法

1. 条件过滤(允许特定参数)

只允许从标准输入(fd=0)读取:

1
2
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1, 
SCMP_A0(SCMP_CMP_EQ, 0)); // 只允许 fd=0

2. 错误处理代替终止

非法调用时返回错误码(代替杀死进程):

1
seccomp_init(SCMP_ACT_ERRNO(EPERM)); // 返回 EPERM 错误

3. 多架构支持

适配 x86_64 和 ARM:

1
2
seccomp_arch_add(ctx, SCMP_ARCH_X86_64);
seccomp_arch_add(ctx, SCMP_ARCH_ARM);

调试技巧

  1. 检查所需系统调用
    1
    strace -c ./your_program  # 统计使用的 syscall
  2. 测试规则
    使用 SCMP_ACT_LOG 记录违规但不终止进程:
    1
    seccomp_init(SCMP_ACT_LOG);  // 仅记录违规

常见问题

  1. 缺失必要系统调用
    程序崩溃或功能异常(如缺失 brk 可能导致内存分配失败)。
  2. 信号处理冲突
    确保允许 rt_sigreturn(通常由 libseccomp 自动处理)。
  3. 性能影响
    BPF 过滤器对性能影响极小(通常 < 0.5%)。

应用场景

  • 容器安全(Docker 默认使用 seccomp 配置文件)
  • 沙盒化不可信代码
  • 特权进程降权(如 Chromium 渲染进程)

通过合理配置 seccomp,可显著提升 Linux 应用程序的安全性。