Seccomp-BPFSecure Computing - Berkeley Packet Filter是 Linux 内核提供的系统调用过滤安全机制核心作用是限制进程能调用的内核系统调用大幅降低程序被攻击后利用内核漏洞提权 / 逃逸的风险。它是容器安全Docker/K8s、沙箱、浏览器、物联网设备安全的核心技术。核心概念SeccompLinux 原生安全模块用于限制进程系统调用BPF内核虚拟机允许用户编写轻量级规则在内核态高效过滤系统调用工作模式strict模式仅允许read/write/exit/sigreturn4 个调用极少用filter 模式BPF自定义白名单 / 黑名单规则灵活控制主流用法工作原理进程通过prctl(PR_SET_SECCOMP,...)或seccomp()加载 BPF 过滤规则进程发起任何系统调用时内核先触发 BPF 规则检查BPF 程序返回结果ALLOW允许执行系统调用DENY拒绝调用返回错误 / 杀死进程规则在内核态执行性能损耗极低极简示例禁止open系统调用#include stdio.h #include unistd.h #include sys/prctl.h #include linux/seccomp.h #include linux/filter.h #include sys/syscall.h int main() { // 1. 定义 BPF 过滤规则禁止 open 系统调用 struct sock_filter filter[] { // 加载系统调用号到寄存器 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), // 如果是 __NR_open返回 KILL 杀死进程 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 0, 1), BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), // 其他系统调用允许 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), }; struct sock_fprog prog { .len sizeof(filter) / sizeof(filter[0]), .filter filter, }; // 2. 必须先设置 NO_NEW_PRIVS否则 seccomp 无法生效 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); // 3. 加载 seccomp-bpf 规则 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog); // 测试调用 open 会直接被内核杀死 printf(尝试打开文件...\n); open(/etc/passwd, 0); printf(此行不会执行\n); return 0; }高级用法使用 libseccomp简化开发手写 BPF 字节码极繁琐libseccomp是官方封装库用 C 语言 API 直接定义规则。安装依赖# Ubuntu/Debian apt install libseccomp-dev # CentOS/RHEL yum install libseccomp-devel示例白名单模式仅允许 3 个系统调用#include stdio.h #include seccomp.h #include sys/syscall.h #include unistd.h int main() { // 1. 创建 seccomp 上下文默认拒绝所有系统调用 scmp_filter_ctx ctx seccomp_init(SCMP_ACT_KILL); // 2. 添加白名单仅允许这 3 个调用 seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); // 3. 加载规则到内核 seccomp_load(ctx); // 测试允许的调用正常执行 printf(PID: %d\n, getpid()); write(1, Hello\n, 6); // 测试禁止的调用会被杀死 open(/etc/hosts, 0); // 释放上下文 seccomp_release(ctx); return 0; }Seccomp-BPF 核心应用场景容器安全Docker/K8s 默认启用 seccomp 配置限制容器内进程调用高危系统调用如mount/reboot防止容器逃逸浏览器安全Chrome/Chromium 用 seccomp 沙箱隔离渲染进程沙箱 / 安全软件限制不可信代码的内核权限物联网 / 嵌入式设备最小化设备攻击面关键命令工具查看进程 seccomp 状态grep Seccomp /proc/[PID]/status # 0关闭 1strict 2filter(BPF)容器查看 seccompdocker run --security-opt seccomp/path/to/profile.json ubuntu生成 BPF 规则seccomp_export_bpf ctx ./rule.bpf规则结构优化1. 优先使用「白名单」禁用「黑名单」白名单默认拒绝所有只允许少量必要系统调用 →检查次数极少黑名单默认允许只拦截少数 →每次都要遍历所有规则✅优化业务一律用白名单模式性能提升 50%。2. 高频系统调用放在规则最前面BPF 是顺序匹配匹配到就返回不再执行后续指令。把read/write/epoll/getpid这类每秒调用百万次的系统调用放在 BPF 规则第一条。❌ 坏写法高频调用在最后LD nr JEQ mkdir, KILL JEQ mount, KILL ... 10条规则 ... JEQ write, ALLOW // 最常用反而放最后✅ 好写法高频调用置顶LD nr JEQ write, ALLOW // 第一顺位 JEQ read, ALLOW JEQ epoll_wait, ALLOW ... 其他规则 ...3. 合并连续判断减少 JMP 指令手写 BPF 时避免冗余跳转用 libseccomp 会自动优化但要避免重复添加规则。BPF 指令级优化1. 仅加载必需的 seccomp_data 字段BPF 检查只需要系统调用号nr不要加载 args/arch 等无关字段。✅ 最优指令BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr))不要加载其他偏移量减少内存读取。2. 避免使用「参数检查」除非必须检查系统调用参数如打开的文件路径、socket 地址会极大增加开销只检查调用号纳秒级检查参数微秒级慢 10~100 倍✅ 优化原则能只限制系统调用号就绝不检查参数安全必须检查参数时只检查关键 1~2 个参数3. 统一使用快速返回码SECCOMP_RET_ALLOW/SECCOMP_RET_KILL是内核最快处理避免使用SECCOMP_RET_TRAP/SECCOMP_RET_ERRNO需要用户态处理慢libseccomp 编译与配置优化1. 开启 libseccomp 优化编译编译时开启 GCC 优化让规则生成更紧凑gcc -O2 -lseccomp ... # O2 优化必开2. 禁用 syscall 重映射简化匹配seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 1); // 保持开启 seccomp_attr_set(ctx, SCMP_FLTATR_API_TSKIP, 0); // 关闭跳过减少判断3. 预编译规则不要动态生成BPF 规则一次性加载不要在运行时频繁增删规则加载操作有开销。容器 / Docker 场景专用优化1. 使用精简的 seccomp 模板Docker 默认模板有 300 系统调用业务容器可精简到 50 个以内。2. 共享相同 BPF 程序同类型容器内核会自动缓存复用 BPF 程序无需重复解析。3. 关闭不必要的能力CAP seccomp 配合减少系统调用检查范围。核心总结本质内核级系统调用防火墙用 BPF 实现轻量过滤优势性能高、内核原生、配置灵活、无额外依赖最佳实践白名单模式默认拒绝仅允许必要调用栈手写 BPF → libseccomp → 容器 / 沙箱集成Seccomp-BPF 是 Linux 最核心的系统调用安全限制机制开发优先用libseccomp避免手写 BPF 字节码生产环境必用容器、沙箱、高敏感服务核心效果大幅降低内核攻击面防止权限提升 / 逃逸
Seccomp-BPF
Seccomp-BPFSecure Computing - Berkeley Packet Filter是 Linux 内核提供的系统调用过滤安全机制核心作用是限制进程能调用的内核系统调用大幅降低程序被攻击后利用内核漏洞提权 / 逃逸的风险。它是容器安全Docker/K8s、沙箱、浏览器、物联网设备安全的核心技术。核心概念SeccompLinux 原生安全模块用于限制进程系统调用BPF内核虚拟机允许用户编写轻量级规则在内核态高效过滤系统调用工作模式strict模式仅允许read/write/exit/sigreturn4 个调用极少用filter 模式BPF自定义白名单 / 黑名单规则灵活控制主流用法工作原理进程通过prctl(PR_SET_SECCOMP,...)或seccomp()加载 BPF 过滤规则进程发起任何系统调用时内核先触发 BPF 规则检查BPF 程序返回结果ALLOW允许执行系统调用DENY拒绝调用返回错误 / 杀死进程规则在内核态执行性能损耗极低极简示例禁止open系统调用#include stdio.h #include unistd.h #include sys/prctl.h #include linux/seccomp.h #include linux/filter.h #include sys/syscall.h int main() { // 1. 定义 BPF 过滤规则禁止 open 系统调用 struct sock_filter filter[] { // 加载系统调用号到寄存器 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), // 如果是 __NR_open返回 KILL 杀死进程 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 0, 1), BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), // 其他系统调用允许 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), }; struct sock_fprog prog { .len sizeof(filter) / sizeof(filter[0]), .filter filter, }; // 2. 必须先设置 NO_NEW_PRIVS否则 seccomp 无法生效 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); // 3. 加载 seccomp-bpf 规则 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog); // 测试调用 open 会直接被内核杀死 printf(尝试打开文件...\n); open(/etc/passwd, 0); printf(此行不会执行\n); return 0; }高级用法使用 libseccomp简化开发手写 BPF 字节码极繁琐libseccomp是官方封装库用 C 语言 API 直接定义规则。安装依赖# Ubuntu/Debian apt install libseccomp-dev # CentOS/RHEL yum install libseccomp-devel示例白名单模式仅允许 3 个系统调用#include stdio.h #include seccomp.h #include sys/syscall.h #include unistd.h int main() { // 1. 创建 seccomp 上下文默认拒绝所有系统调用 scmp_filter_ctx ctx seccomp_init(SCMP_ACT_KILL); // 2. 添加白名单仅允许这 3 个调用 seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); // 3. 加载规则到内核 seccomp_load(ctx); // 测试允许的调用正常执行 printf(PID: %d\n, getpid()); write(1, Hello\n, 6); // 测试禁止的调用会被杀死 open(/etc/hosts, 0); // 释放上下文 seccomp_release(ctx); return 0; }Seccomp-BPF 核心应用场景容器安全Docker/K8s 默认启用 seccomp 配置限制容器内进程调用高危系统调用如mount/reboot防止容器逃逸浏览器安全Chrome/Chromium 用 seccomp 沙箱隔离渲染进程沙箱 / 安全软件限制不可信代码的内核权限物联网 / 嵌入式设备最小化设备攻击面关键命令工具查看进程 seccomp 状态grep Seccomp /proc/[PID]/status # 0关闭 1strict 2filter(BPF)容器查看 seccompdocker run --security-opt seccomp/path/to/profile.json ubuntu生成 BPF 规则seccomp_export_bpf ctx ./rule.bpf规则结构优化1. 优先使用「白名单」禁用「黑名单」白名单默认拒绝所有只允许少量必要系统调用 →检查次数极少黑名单默认允许只拦截少数 →每次都要遍历所有规则✅优化业务一律用白名单模式性能提升 50%。2. 高频系统调用放在规则最前面BPF 是顺序匹配匹配到就返回不再执行后续指令。把read/write/epoll/getpid这类每秒调用百万次的系统调用放在 BPF 规则第一条。❌ 坏写法高频调用在最后LD nr JEQ mkdir, KILL JEQ mount, KILL ... 10条规则 ... JEQ write, ALLOW // 最常用反而放最后✅ 好写法高频调用置顶LD nr JEQ write, ALLOW // 第一顺位 JEQ read, ALLOW JEQ epoll_wait, ALLOW ... 其他规则 ...3. 合并连续判断减少 JMP 指令手写 BPF 时避免冗余跳转用 libseccomp 会自动优化但要避免重复添加规则。BPF 指令级优化1. 仅加载必需的 seccomp_data 字段BPF 检查只需要系统调用号nr不要加载 args/arch 等无关字段。✅ 最优指令BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr))不要加载其他偏移量减少内存读取。2. 避免使用「参数检查」除非必须检查系统调用参数如打开的文件路径、socket 地址会极大增加开销只检查调用号纳秒级检查参数微秒级慢 10~100 倍✅ 优化原则能只限制系统调用号就绝不检查参数安全必须检查参数时只检查关键 1~2 个参数3. 统一使用快速返回码SECCOMP_RET_ALLOW/SECCOMP_RET_KILL是内核最快处理避免使用SECCOMP_RET_TRAP/SECCOMP_RET_ERRNO需要用户态处理慢libseccomp 编译与配置优化1. 开启 libseccomp 优化编译编译时开启 GCC 优化让规则生成更紧凑gcc -O2 -lseccomp ... # O2 优化必开2. 禁用 syscall 重映射简化匹配seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 1); // 保持开启 seccomp_attr_set(ctx, SCMP_FLTATR_API_TSKIP, 0); // 关闭跳过减少判断3. 预编译规则不要动态生成BPF 规则一次性加载不要在运行时频繁增删规则加载操作有开销。容器 / Docker 场景专用优化1. 使用精简的 seccomp 模板Docker 默认模板有 300 系统调用业务容器可精简到 50 个以内。2. 共享相同 BPF 程序同类型容器内核会自动缓存复用 BPF 程序无需重复解析。3. 关闭不必要的能力CAP seccomp 配合减少系统调用检查范围。核心总结本质内核级系统调用防火墙用 BPF 实现轻量过滤优势性能高、内核原生、配置灵活、无额外依赖最佳实践白名单模式默认拒绝仅允许必要调用栈手写 BPF → libseccomp → 容器 / 沙箱集成Seccomp-BPF 是 Linux 最核心的系统调用安全限制机制开发优先用libseccomp避免手写 BPF 字节码生产环境必用容器、沙箱、高敏感服务核心效果大幅降低内核攻击面防止权限提升 / 逃逸