#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;
}