// SPDX-License-Identifier: AGPL-3.0-or-later /* SEITAN - Syscall Expressive Interpreter, Transformer and Notifier * * eater.c - Load BPF program and execute binary * * Copyright (c) 2022 Red Hat GmbH * Author: Stefano Brivio */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include extern char **environ; static char *qemu_names[] = { "kvm", "qemu-kvm", #ifdef ARCH ( "qemu-system-" ARCH ), #endif "/usr/libexec/qemu-kvm", NULL, }; /** * usage() - Print usage and exit */ void usage(void) { fprintf(stderr, "Usage: seitan-eater [QEMU_ARG]...\n"); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } static int seccomp(unsigned int operation, unsigned int flags, void *args) { return syscall(__NR_seccomp, operation, flags, args); } /** * main() - Entry point * @argc: Argument count * @argv: qemu arguments * * Return: 0 once interrupted, non-zero on failure */ int main(int argc, char **argv) { int fd = open("bpf.out", O_CLOEXEC | O_RDONLY); struct sock_filter filter[1024]; struct sock_fprog prog; char **name; size_t n; (void)argc; n = read(fd, filter, sizeof(filter)); close(fd); prog.filter = filter; prog.len = (unsigned short)(n / sizeof(filter[0])); prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); fd = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog); connect(0, NULL, 0); /* Wait for seitan to unblock this */ for (name = qemu_names; *name; name++) { argv[0] = *name; execvpe(*name, argv, environ); if (errno != ENOENT) { perror("execvpe"); usage(); } } perror("execvpe"); return EXIT_FAILURE; }