#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <stddef.h>
int main() {
// BPF программа: разрешаем только write и exit_group
struct sock_filter filter[] = {
// Загружаем номер системного вызова
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
offsetof(struct seccomp_data, nr)),
// Если это write (номер 1) -> разрешить
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 1, 0),
// Если это exit_group (номер 231) -> разрешить
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 231, 1, 0),
// Иначе - убить процесс
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
// Разрешить syscall
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = sizeof(filter) / sizeof(filter[0]),
.filter = filter,
};
// Обязательно: запрещаем получение привилегий
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
perror("prctl");
return 1;
}
// Устанавливаем фильтр
if (syscall(SYS_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog) == -1) {
perror("seccomp");
return 1;
}
printf("Seccomp фильтр активен! Разрешены только write и exit_group\n");
printf("Эта строка выведется (write разрешен)\n");
// Пытаемся выполнить запрещенный syscall - процесс будет убит
printf("Сейчас попробуем выполнить fork() - процесс будет убит\n");
sleep(1);
fork(); // Это убьет процесс
// Сюда программа никогда не дойдет
printf("Это сообщение никогда не появится\n");
return 0;
}