如何从C语言或终端为目标进程单独应用seccomp安全规则
问题根因
你当前的执行顺序是「加载seccomp规则」→「调用execl执行目标命令」,而seccomp规则加载后会立即对当前进程的所有后续系统调用生效,execl执行过程中需要的系统调用(比如内部调用的execve,动态编译场景下的其他依赖调用)不在你允许的规则里,就会被拦截。
方案1:C语言原生实现
核心修改逻辑:构造seccomp规则时额外允许当前进程调用execve,保证execl正常运行,当前进程执行execve之后,生成的目标命令进程会继承剩余的严格seccomp规则。
前置依赖
先安装libseccomp开发库:sudo apt install libseccomp-dev
完整代码示例
#include <seccomp.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { scmp_filter_ctx filter; // 初始化过滤器,默认违反规则直接杀死进程 filter = seccomp_init(SCMP_ACT_KILL); if (filter == NULL) { perror("seccomp_init failed"); return 1; } // 允许当前进程执行execve,保证execl正常运行 if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(execve), 0) != 0) { perror("add execve rule failed"); goto err; } // 目标命令允许规则:仅允许向stdout(1)、stderr(2)写内容 if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_LE, 2)) != 0) { perror("add write rule failed"); goto err; } // 允许进程退出相关系统调用 if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0) != 0) { perror("add exit rule failed"); goto err; } // --- 如果目标程序是动态链接,需要取消注释以下规则,允许加载动态库 --- /* if (seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(open), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(access), 0) != 0 || seccomp_rule_add(filter, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0) != 0) { perror("add dynamic link rule failed"); goto err; } */ // 加载seccomp规则 if (seccomp_load(filter) != 0) { perror("seccomp_load failed"); goto err; } // 执行目标命令,注意execl第一个参数为程序路径,最后一个参数必须为NULL execl("/bin/ls", "ls", NULL); perror("execl failed"); err: seccomp_release(filter); return 1; }
编译命令
gcc -o seccomp_runner seccomp_runner.c -lseccomp
注意:如果要求目标命令完全禁止读写任何文件,目标命令必须是静态编译的,否则动态链接过程需要读取系统动态库文件,必然会触发文件读操作,无法正常启动。
方案2:现成工具实现(无需写C代码)
Ubuntu 18.04可以直接用firejail工具快速实现需求:
- 安装firejail:
sudo apt install firejail - 运行命令示例:
firejail --seccomp --private=/tmp/empty --read-only=/ --allow=/dev/stdout --allow=/dev/stderr ls
该配置会自动为目标进程加载seccomp规则,禁止所有未授权的系统调用,仅允许写入控制台,无法读写其他文件。
内容的提问来源于stack exchange,提问作者user100123122
相关产品推荐
相关产品推荐

