Linux seccomp介绍及demo示例

Linux seccomp 介绍

seccomp(Secure Computing Mode) 是 Linux 内核的安全机制,用于限制进程可执行的系统调用(syscalls)。通过过滤系统调用,seccomp 能有效减少内核暴露的攻击面,提升应用安全性。它有两种工作模式:

  1. 严格模式(strict mode)
    只允许 read(), write(), _exit(), sigreturn() 四个系统调用,其他调用会触发 SIGKILL

  2. 过滤模式(filter mode / seccomp-bpf)
    使用 BPF(Berkeley Packet Filter)规则 自定义允许/禁止的系统调用,支持精细控制(如参数检查、返回错误码而非终止进程)。


示例:使用 libseccomp 的过滤模式 Demo

场景说明

创建一个程序,仅允许:

  1. 退出进程(exit_group
  2. 内存分配(brk,由 malloc 触发)
  3. 向终端输出(write
  4. 从终端读取(read

禁止其他所有系统调用(如文件操作)。

代码实现

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

void init_seccomp() {
// 初始化 seccomp 上下文,默认禁止所有系统调用
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);

// 添加允许的系统调用(规则优先级从高到低)
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); // 允许退出
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); // 允许内存分配
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // 允许写文件描述符
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); // 允许读文件描述符

// 加载规则到内核
seccomp_load(ctx);
seccomp_release(ctx); // 释放资源
}

int main() {
// 初始化 seccomp 过滤器
init_seccomp();

// 测试允许的操作
printf("Hello, seccomp!\n"); // 允许:使用 write 输出

// 测试禁止的操作(解除注释会触发 SIGKILL)
// FILE *fp = fopen("test.txt", "w"); // 禁止:调用 openat

// 等待用户输入(验证 read 是否允许)
char buf[10];
printf("Enter something: ");
read(STDIN_FILENO, buf, sizeof(buf)); // 允许:使用 read

return 0; // 允许:触发 exit_group
}

编译与运行

  1. 安装依赖(Ubuntu):

    1
    sudo apt-get install libseccomp-dev gcc
  2. 编译程序:

    1
    gcc seccomp_demo.c -o seccomp_demo -lseccomp
  3. 运行测试:

    1
    ./seccomp_demo

    输出示例

    1
    2
    Hello, seccomp!
    Enter something: [输入任意字符后程序正常退出]
  4. 测试违规操作:
    取消 fopen 的注释后重新编译运行,程序会立即终止(触发 SIGKILL)。


关键函数说明

函数 作用
seccomp_init(SCMP_ACT_KILL) 初始化上下文,默认禁止所有系统调用
seccomp_rule_add(ctx, action, syscall, 0) 添加规则(0 表示无条件允许)
seccomp_load(ctx) 将规则加载到内核
seccomp_release(ctx) 释放上下文资源

高级用法

  1. 参数过滤
    只允许特定参数的系统调用,例如仅允许向标准输出(fd=1)写入:

    1
    2
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, 
    SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO)); // 检查第一个参数 fd==1
  2. 返回错误码
    禁止系统调用时返回错误码(而非终止进程):

    1
    seccomp_init(SCMP_ACT_ERRNO(EPERM));  // 返回 EPERM 错误
  3. 调试规则
    导出规则到文件:

    1
    seccomp_export_bpf(ctx, f);  // 将 BPF 规则写入文件描述符 f

应用场景

  • 容器安全(Docker、Kubernetes)
  • 浏览器沙箱(Chrome、Firefox)
  • 敏感服务(如密钥管理)
  • 防止提权攻击

通过 seccomp,开发者能主动定义进程的“权限边界”,极大增强 Linux 应用的纵深防御能力。