1485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#ifdef HAVE_CONFIG_H
2485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin# include "config.h"
3485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#endif
4485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
5485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#include <stddef.h>
6485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#include <unistd.h>
7485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#include <stdio.h>
8485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#include <errno.h>
9485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#include <sys/syscall.h>
10485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
11485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#ifdef HAVE_PRCTL
12485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin# include <sys/prctl.h>
13485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#endif
14485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#ifdef HAVE_LINUX_SECCOMP_H
15485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin# include <linux/seccomp.h>
16485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#endif
17485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#ifdef HAVE_LINUX_FILTER_H
18485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin# include <linux/filter.h>
19485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#endif
20485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
21485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#if defined HAVE_PRCTL \
22485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined PR_SET_NO_NEW_PRIVS \
23485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined PR_SET_SECCOMP \
24485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined SECCOMP_MODE_FILTER \
25485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined SECCOMP_RET_ERRNO \
26485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined BPF_JUMP \
27485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin && defined BPF_STMT
28485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
29485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#define SOCK_FILTER_ALLOW_SYSCALL(nr) \
30485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \
31485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
32485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
33485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#define SOCK_FILTER_DENY_SYSCALL(nr, err) \
34485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \
35485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (SECCOMP_RET_DATA & (err)))
36485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
37485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#define SOCK_FILTER_KILL_PROCESS \
38485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)
39485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
40485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#define PRINT_ALLOW_SYSCALL(nr) \
41485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \
42485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	       "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), ", \
43485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	       __NR_ ## nr)
44485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
45485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#define PRINT_DENY_SYSCALL(nr, err) \
46485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \
47485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	       "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | %#x), ", \
48485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	       __NR_ ## nr, err)
49485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
50485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levinstatic const struct sock_filter filter[] = {
51485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	/* load syscall number */
52485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
53485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
54485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	/* allow syscalls */
55485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_ALLOW_SYSCALL(close),
56485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_ALLOW_SYSCALL(exit),
57485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_ALLOW_SYSCALL(exit_group),
58485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
59485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	/* deny syscalls */
60485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_DENY_SYSCALL(sync, EBUSY),
61485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_DENY_SYSCALL(setsid, EPERM),
62485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
63485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	/* kill process */
64485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	SOCK_FILTER_KILL_PROCESS
65485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin};
66485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
67485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levinstatic const struct sock_fprog prog = {
68485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	.len = sizeof(filter) / sizeof(filter[0]),
69485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	.filter = (struct sock_filter *) filter,
70485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin};
71485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
72485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levinint
73485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levinmain(void)
74485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin{
75485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	int fds[2];
76485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
77485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)  = 0");
78485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
79485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, [");
80485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
81485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	printf("BPF_STMT(BPF_LD | BPF_W | BPF_ABS, %#x), ",
82485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	       (unsigned) offsetof(struct seccomp_data, nr));
83485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
84485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	PRINT_ALLOW_SYSCALL(close);
85485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	PRINT_ALLOW_SYSCALL(exit);
86485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	PRINT_ALLOW_SYSCALL(exit_group);
87485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
88485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	PRINT_DENY_SYSCALL(sync, EBUSY),
89485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	PRINT_DENY_SYSCALL(setsid, EPERM),
90485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
91485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	printf("BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)");
92485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
93485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	puts("]) = 0");
94485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	puts("+++ exited with 0 +++");
95485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
96485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	fflush(stdout);
97485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	close(0);
98485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	close(1);
99485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
100485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	if (pipe(fds) ||
101485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
102485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) ||
103485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	    close(0) || close(1))
104485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin		_exit(77);
105485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
106485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin	_exit(0);
107485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin}
108485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
109485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#else
110485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
111485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levinint main(void) { return 77; }
112485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin
113485f8fb2500980be2cb0cde43e3582c088739a6fDmitry V. Levin#endif
114