使用Seccomp与execve执行C/C++程序遇错误码159、信号31求助
问题描述
尝试通过Seccomp与execve构建安全环境执行C/C++程序,但程序无法正常运行,执行时退出状态码为159,触发信号31(SIGSYS,代表系统调用被Seccomp策略拦截)。以下是相关代码文件及操作步骤,请求协助排查:
seccomp_rules.c
#include <stdio.h> #include <seccomp.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdbool.h> #include "seccomp_rules.h" int c_cpp_seccomp_rules(struct config *_config, bool allow_write_file) { int syscalls_whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat), SCMP_SYS(mmap), SCMP_SYS(mprotect), SCMP_SYS(munmap), SCMP_SYS(uname), SCMP_SYS(arch_prctl), SCMP_SYS(brk), SCMP_SYS(access), SCMP_SYS(exit_group), SCMP_SYS(close), SCMP_SYS(readlink), SCMP_SYS(sysinfo), SCMP_SYS(write), SCMP_SYS(writev), SCMP_SYS(lseek), SCMP_SYS(clock_gettime), SCMP_SYS(pread64)}; // 添加pread64系统调用规则 int syscalls_whitelist_length = sizeof(syscalls_whitelist) / sizeof(int); scmp_filter_ctx ctx = NULL; // 初始化Seccomp,默认动作是拦截并终止进程 ctx = seccomp_init(SCMP_ACT_KILL); if (!ctx) { return LOAD_SECCOMP_FAILED; } // 添加白名单系统调用规则 for (int i = 0; i < syscalls_whitelist_length; i++) { if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls_whitelist[i], 0) != 0) { return LOAD_SECCOMP_FAILED; } } // 允许执行指定路径的execve调用 if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)(_config->exe_path))) != 0) { return LOAD_SECCOMP_FAILED; } if (!allow_write_file) { // 仅允许以只读模式打开文件 if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) { return LOAD_SECCOMP_FAILED; } if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) { return LOAD_SECCOMP_FAILED; } } else { // 允许任意模式打开文件 if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0) != 0) { return LOAD_SECCOMP_FAILED; } // 允许文件描述符复制操作 if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0) != 0) { return LOAD_SECCOMP_FAILED; } if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0) != 0) { return LOAD_SECCOMP_FAILED; } if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 0) != 0) { return LOAD_SECCOMP_FAILED; } } // 加载Seccomp策略 if (seccomp_load(ctx) != 0) { return LOAD_SECCOMP_FAILED; } seccomp_release(ctx); return 0; }
main.c
temp.c是一个简单的C文件,temp是尝试在项目中执行的C目标文件
#include <stdio.h> #include <seccomp.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdbool.h> #include "seccomp_rules.h" int main() { struct config _config; long orig_eax; _config.exe_path = "/home/ubuntu/runner/temp"; _config.args[0] = _config.exe_path; _config.args[1] = NULL; _config.env[0] = "PATH=/usr/local/bin:/usr/bin:/bin"; _config.env[1] = "LANG=en_US.UTF-8"; _config.env[2] = "LANGUAGE=en_US:en"; _config.env[3] = "LC_ALL=en_US.UTF-8"; _config.env[4] = NULL; // 创建子进程 pid_t child_pid = fork(); // pid < 0表示克隆失败 if (child_pid < 0) { printf("FORK_FAILED"); } else if (child_pid == 0) { // 加载Seccomp规则,允许写入文件 c_cpp_seccomp_rules(&_config, true); // 执行目标程序 execve(_config.exe_path, _config.args, _config.env); // 如果execve返回,说明执行失败 printf("execve failed\n"); } else if (child_pid > 0) { // 父进程暂未处理子进程退出逻辑 } }
seccomp_rules.h
#ifndef SECCOMP_RULES_H #define SECCOMP_RULES_H #include <stdbool.h> #include <sys/types.h> #define LOAD_SECCOMP_FAILED -1; struct config { char *exe_path; char *args[20]; char *env[20]; }; int c_cpp_seccomp_rules(struct config *_config, bool allow_write_file); #endif // SECCOMP_RULES_H
CMakeLists.txt
cmake_minimum_required(VERSION 2.5) # set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") # SET (CMAKE_C_COMPILER_WORKS 1) # SET (CMAKE_CXX_COMPILER_WORKS 1) project(Seccomp) #set(CMAKE_VERBOSE_MAKEFILE ON) # 设置可执行文件输出目录 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output) # 设置C编译选项 set(CMAKE_C_FLAGS "-g -Wall -O3 -std=c99 -pie -fPIC") # 收集所有C源文件 file(GLOB SOURCE "./*.c") # 创建可执行文件(注意:这里命名为seccomp.so,但实际是可执行程序,建议改为seccomp_runner) add_executable(seccomp.so ${SOURCE}) # 链接依赖库 target_link_libraries(seccomp.so pthread seccomp) # 安装规则 install(FILES output/seccomp.so PERMISSIONS OWNER_EXECUTE OWNER_READ DESTINATION /usr/lib/runner)
操作步骤
将所有文件放入同一文件夹后执行以下命令:
cmake . && make./output/seccomp.so
内容的提问来源于stack exchange,提问作者Vikram Ayaluri
相关产品推荐
相关产品推荐

