162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Naive system call dropper built on seccomp_filter.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
662306a36Sopenharmony_ci * Author: Will Drewry <wad@chromium.org>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * The code may be used by anyone for any purpose,
962306a36Sopenharmony_ci * and can serve as a starting point for developing
1062306a36Sopenharmony_ci * applications using prctl(PR_SET_SECCOMP, 2, ...).
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * When run, returns the specified errno for the specified
1362306a36Sopenharmony_ci * system call number against the given architecture.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <errno.h>
1862306a36Sopenharmony_ci#include <linux/audit.h>
1962306a36Sopenharmony_ci#include <linux/filter.h>
2062306a36Sopenharmony_ci#include <linux/seccomp.h>
2162306a36Sopenharmony_ci#include <linux/unistd.h>
2262306a36Sopenharmony_ci#include <stdio.h>
2362306a36Sopenharmony_ci#include <stddef.h>
2462306a36Sopenharmony_ci#include <stdlib.h>
2562306a36Sopenharmony_ci#include <sys/prctl.h>
2662306a36Sopenharmony_ci#include <unistd.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int install_filter(int arch, int nr, int error)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	struct sock_filter filter[] = {
3162306a36Sopenharmony_ci		BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
3262306a36Sopenharmony_ci			 (offsetof(struct seccomp_data, arch))),
3362306a36Sopenharmony_ci		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, arch, 0, 3),
3462306a36Sopenharmony_ci		BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
3562306a36Sopenharmony_ci			 (offsetof(struct seccomp_data, nr))),
3662306a36Sopenharmony_ci		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, nr, 0, 1),
3762306a36Sopenharmony_ci		BPF_STMT(BPF_RET+BPF_K,
3862306a36Sopenharmony_ci			 SECCOMP_RET_ERRNO|(error & SECCOMP_RET_DATA)),
3962306a36Sopenharmony_ci		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
4062306a36Sopenharmony_ci	};
4162306a36Sopenharmony_ci	struct sock_fprog prog = {
4262306a36Sopenharmony_ci		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
4362306a36Sopenharmony_ci		.filter = filter,
4462306a36Sopenharmony_ci	};
4562306a36Sopenharmony_ci	if (error == -1) {
4662306a36Sopenharmony_ci		struct sock_filter kill = BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL);
4762306a36Sopenharmony_ci		filter[4] = kill;
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
5062306a36Sopenharmony_ci		perror("prctl(NO_NEW_PRIVS)");
5162306a36Sopenharmony_ci		return 1;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci	if (prctl(PR_SET_SECCOMP, 2, &prog)) {
5462306a36Sopenharmony_ci		perror("prctl(PR_SET_SECCOMP)");
5562306a36Sopenharmony_ci		return 1;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci	return 0;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ciint main(int argc, char **argv)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	if (argc < 5) {
6362306a36Sopenharmony_ci		fprintf(stderr, "Usage:\n"
6462306a36Sopenharmony_ci			"dropper <arch> <syscall_nr> <errno> <prog> [<args>]\n"
6562306a36Sopenharmony_ci			"Hint:	AUDIT_ARCH_I386: 0x%X\n"
6662306a36Sopenharmony_ci			"	AUDIT_ARCH_X86_64: 0x%X\n"
6762306a36Sopenharmony_ci			"	errno == -1 means SECCOMP_RET_KILL\n"
6862306a36Sopenharmony_ci			"\n", AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
6962306a36Sopenharmony_ci		return 1;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci	if (install_filter(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0),
7262306a36Sopenharmony_ci			   strtol(argv[3], NULL, 0)))
7362306a36Sopenharmony_ci		return 1;
7462306a36Sopenharmony_ci	execv(argv[4], &argv[4]);
7562306a36Sopenharmony_ci	printf("Failed to execv\n");
7662306a36Sopenharmony_ci	return 255;
7762306a36Sopenharmony_ci}
78