3 #if defined(__FreeBSD__)
5 #include <sys/capsicum.h>
14 for (h = hosts; h->domain != NULL; ++h)
18 if (cap_enter() == -1)
22 #elif defined(__linux__)
24 #include <sys/prctl.h>
25 #include <sys/syscall.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
29 #include <linux/audit.h>
30 #include <linux/filter.h>
31 #include <linux/seccomp.h>
39 /* thanks chromium' src/seccomp.c */
41 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
42 #elif defined(__x86_64__)
43 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
44 #elif defined(__arm__)
45 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
46 #elif defined(__aarch64__)
47 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
48 #elif defined(__mips__)
49 # if defined(__mips64)
50 # if defined(__MIPSEB__)
51 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
53 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
56 # if defined(__MIPSEB__)
57 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
59 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
63 # error "Platform does not support seccomp filter yet"
66 /* uncomment to enable debugging. ONLY FOR DEVELOPMENT */
67 /* #define SC_DEBUG */
70 # define SC_FAIL SECCOMP_RET_TRAP
72 # define SC_FAIL SECCOMP_RET_KILL
75 /* make the filter more readable */
76 #define SC_ALLOW(nr) \
77 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \
78 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
86 sandbox_seccomp_violation(int signum, siginfo_t *info, void *ctx)
91 fprintf(stderr, "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)\n",
92 __func__, info->si_arch, info->si_syscall, info->si_call_addr);
97 sandbox_seccomp_catch_sigsys(void)
102 memset(&act, 0, sizeof(act));
104 sigaddset(&mask, SIGSYS);
106 act.sa_sigaction = &sandbox_seccomp_violation;
107 act.sa_flags = SA_SIGINFO;
108 if (sigaction(SIGSYS, &act, NULL) == -1) {
109 fprintf(stderr, "%s: sigaction(SIGSYS): %s\n",
110 __func__, strerror(errno));
113 if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) {
114 fprintf(stderr, "%s: sigprocmask(SIGSYS): %s\n",
115 __func__, strerror(errno));
119 #endif /* SC_DEBUG */
124 struct sock_filter filter[] = {
125 /* load the *current* architecture */
126 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
127 (offsetof(struct seccomp_data, arch))),
128 /* ensure it's the same that we've been compiled on */
129 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
130 SECCOMP_AUDIT_ARCH, 1, 0),
131 /* if not, kill the program */
132 BPF_STMT(BPF_RET | BPF_K, SC_FAIL),
134 /* load the syscall number */
135 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
136 (offsetof(struct seccomp_data, nr))),
138 /* allow logging on stdout */
143 /* these are used to serve the files. note how we
144 * allow openat but not open. */
157 /* we need recvmsg to receive fd */
164 SC_ALLOW(exit_group),
166 /* allow ioctl but only on fd 1, glibc doing stuff? */
167 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_ioctl, 0, 3),
168 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
169 (offsetof(struct seccomp_data, args[0]))),
170 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 0, 1),
171 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
173 /* disallow enything else */
174 BPF_STMT(BPF_RET | BPF_K, SC_FAIL),
177 struct sock_fprog prog = {
178 .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
183 sandbox_seccomp_catch_sigsys();
186 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
187 fprintf(stderr, "%s: prctl(PR_SET_NO_NEW_PRIVS): %s\n",
188 __func__, strerror(errno));
192 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) == -1) {
193 fprintf(stderr, "%s: prctl(PR_SET_SECCOMP): %s\n",
194 __func__, strerror(errno));
199 #elif defined(__OpenBSD__)
209 for (h = hosts; h->domain != NULL; ++h) {
210 if (unveil(h->dir, "rx") == -1)
211 err(1, "unveil %s for domain %s", h->dir, h->domain);
214 if (pledge("stdio recvfd rpath inet", NULL) == -1)
223 LOGN(NULL, "%s", "no sandbox method known for this OS");