Seccomp简单的使用

#include "iostream"
#include "linux/seccomp.h"
#include "linux/bpf_common.h"
#include "linux/filter.h"
#include "sys/prctl.h"
// 包含系统调用号的头文件
#include <linux/unistd.h>
// 包含架构的头文件
#include <linux/audit.h>
#include <unistd.h>
#include <sys/wait.h>


using namespace std;


#define NR_OFFSET offsetof(struct seccomp_data,  nr)
#define ARCH_OFFSET offsetof(struct seccomp_data, arch)
#define INSTRUCTION_POINTER_OFFSET offsetof(struct seccomp_data, instruction_pointer)
#define ARGS_OFFSET offsetof(struct seccomp_data, args)


int main() {

    int status = 0;
    struct sock_filter filter[] = {
        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ARCH_OFFSET),  // 将指令的架构, ld到"寄存器"
        BPF_JUMP(BPF_JMP+BPF_JEQ, AUDIT_ARCH_X86_64, 1, 0),  // 验证架构是否是64位的系统调用
        BPF_STMT(BPF_RET, SECCOMP_RET_KILL),  // 如果不是, 防止逃逸直接kill

        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, NR_OFFSET),  // 获得系统调用号
        BPF_JUMP(BPF_JMP+BPF_JEQ, __NR_exit_group, 0, 1),  // 允许 退出
        BPF_STMT(BPF_RET, SECCOMP_RET_ALLOW),

        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, NR_OFFSET),
        BPF_JUMP(BPF_JMP+BPF_JEQ, __NR_write, 1, 0),  // 允许 write
        BPF_STMT(BPF_RET, SECCOMP_RET_KILL),

        BPF_STMT(BPF_LD+0x18+BPF_ABS, ARGS_OFFSET+8*0),
        BPF_JUMP(BPF_JMP+BPF_JEQ, 0, 1, 0),  // 允许 write 的fd 为0 的调用
        BPF_STMT(BPF_RET, SECCOMP_RET_KILL),

        BPF_STMT(BPF_LDX+0x18+BPF_ABS, ARGS_OFFSET+8*1),

        BPF_STMT(BPF_RET,SECCOMP_RET_ALLOW)
    };

    struct sock_fprog prog = {
           .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
           .filter = filter,
    };

    int sub_pid = fork();

    if (sub_pid == 0) {
        sleep(1);
        prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0);
        prctl(PR_SET_SECCOMP,SECCOMP_MODE_FILTER,&prog);


        write(1, "hello\n", 6);
        // cout << 123 << endl;
        exit(0);
    }

    waitpid(sub_pid, &status, 0);

    if (status == 0) {
        cout << "子进程正常退出" << endl;
    } else {
        cout << "子进程异常, status: " << status << endl;
    }

    return 0;
}