aboutgitcodelistschat:MatrixIRC
path: root/eater.c
blob: a7a6b5fa64465f21369066610172e65c3038633f (plain) (tree)
1
2
3
4
5



                                                                    
                                                





































                                              
                                                               

















































                                                                          
// 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 <sbrivio@redhat.com>
 */

#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/socket.h>

#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>

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