162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Seccomp BPF example using a macro-based generator.
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_ATTACH_SECCOMP_FILTER).
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/filter.h>
1462306a36Sopenharmony_ci#include <linux/seccomp.h>
1562306a36Sopenharmony_ci#include <linux/unistd.h>
1662306a36Sopenharmony_ci#include <stdio.h>
1762306a36Sopenharmony_ci#include <string.h>
1862306a36Sopenharmony_ci#include <sys/prctl.h>
1962306a36Sopenharmony_ci#include <unistd.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "bpf-helper.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#ifndef PR_SET_NO_NEW_PRIVS
2462306a36Sopenharmony_ci#define PR_SET_NO_NEW_PRIVS 38
2562306a36Sopenharmony_ci#endif
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ciint main(int argc, char **argv)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct bpf_labels l = {
3062306a36Sopenharmony_ci		.count = 0,
3162306a36Sopenharmony_ci	};
3262306a36Sopenharmony_ci	static const char msg1[] = "Please type something: ";
3362306a36Sopenharmony_ci	static const char msg2[] = "You typed: ";
3462306a36Sopenharmony_ci	char buf[256];
3562306a36Sopenharmony_ci	struct sock_filter filter[] = {
3662306a36Sopenharmony_ci		/* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */
3762306a36Sopenharmony_ci		LOAD_SYSCALL_NR,
3862306a36Sopenharmony_ci		SYSCALL(__NR_exit, ALLOW),
3962306a36Sopenharmony_ci		SYSCALL(__NR_exit_group, ALLOW),
4062306a36Sopenharmony_ci		SYSCALL(__NR_write, JUMP(&l, write_fd)),
4162306a36Sopenharmony_ci		SYSCALL(__NR_read, JUMP(&l, read)),
4262306a36Sopenharmony_ci		DENY,  /* Don't passthrough into a label */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		LABEL(&l, read),
4562306a36Sopenharmony_ci		ARG(0),
4662306a36Sopenharmony_ci		JNE(STDIN_FILENO, DENY),
4762306a36Sopenharmony_ci		ARG(1),
4862306a36Sopenharmony_ci		JNE((unsigned long)buf, DENY),
4962306a36Sopenharmony_ci		ARG(2),
5062306a36Sopenharmony_ci		JGE(sizeof(buf), DENY),
5162306a36Sopenharmony_ci		ALLOW,
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		LABEL(&l, write_fd),
5462306a36Sopenharmony_ci		ARG(0),
5562306a36Sopenharmony_ci		JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
5662306a36Sopenharmony_ci		JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
5762306a36Sopenharmony_ci		DENY,
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci		LABEL(&l, write_buf),
6062306a36Sopenharmony_ci		ARG(1),
6162306a36Sopenharmony_ci		JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
6262306a36Sopenharmony_ci		JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
6362306a36Sopenharmony_ci		JEQ((unsigned long)buf, JUMP(&l, buf_len)),
6462306a36Sopenharmony_ci		DENY,
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		LABEL(&l, msg1_len),
6762306a36Sopenharmony_ci		ARG(2),
6862306a36Sopenharmony_ci		JLT(sizeof(msg1), ALLOW),
6962306a36Sopenharmony_ci		DENY,
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		LABEL(&l, msg2_len),
7262306a36Sopenharmony_ci		ARG(2),
7362306a36Sopenharmony_ci		JLT(sizeof(msg2), ALLOW),
7462306a36Sopenharmony_ci		DENY,
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		LABEL(&l, buf_len),
7762306a36Sopenharmony_ci		ARG(2),
7862306a36Sopenharmony_ci		JLT(sizeof(buf), ALLOW),
7962306a36Sopenharmony_ci		DENY,
8062306a36Sopenharmony_ci	};
8162306a36Sopenharmony_ci	struct sock_fprog prog = {
8262306a36Sopenharmony_ci		.filter = filter,
8362306a36Sopenharmony_ci		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
8462306a36Sopenharmony_ci	};
8562306a36Sopenharmony_ci	ssize_t bytes;
8662306a36Sopenharmony_ci	bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter));
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
8962306a36Sopenharmony_ci		perror("prctl(NO_NEW_PRIVS)");
9062306a36Sopenharmony_ci		return 1;
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
9462306a36Sopenharmony_ci		perror("prctl(SECCOMP)");
9562306a36Sopenharmony_ci		return 1;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci	syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
9862306a36Sopenharmony_ci	bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
9962306a36Sopenharmony_ci	bytes = (bytes > 0 ? bytes : 0);
10062306a36Sopenharmony_ci	syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
10162306a36Sopenharmony_ci	syscall(__NR_write, STDERR_FILENO, buf, bytes);
10262306a36Sopenharmony_ci	/* Now get killed */
10362306a36Sopenharmony_ci	syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
10462306a36Sopenharmony_ci	return 0;
10562306a36Sopenharmony_ci}
106