You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)

操作步骤

将所有文件放入同一文件夹后执行以下命令:

  1. cmake . && make
  2. ./output/seccomp.so

内容的提问来源于stack exchange,提问作者Vikram Ayaluri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:05:19