1 /* Generate a Secure Computing filter definition file.
3 Copyright (C) 2020-2024 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation, either version 3 of the License, or (at your
10 option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see
19 <https://www.gnu.org/licenses/>. */
21 /* This program creates a small Secure Computing filter usable for a
22 typical minimal Emacs sandbox. See the man page for `seccomp' for
23 details about Secure Computing filters. This program requires the
24 `libseccomp' library. However, the resulting filter file requires
25 only a Linux kernel supporting the Secure Computing extension.
29 seccomp-filter out.bpf out.pfc out-exec.bpf out-exec.pfc
31 This writes the raw `struct sock_filter' array to out.bpf and a
32 human-readable representation to out.pfc. Additionally, it writes
33 variants of those files that can be used to sandbox Emacs before
34 'execve' to out-exec.bpf and out-exec.pfc. */
47 #include <asm/prctl.h>
48 #include <sys/ioctl.h>
50 #include <sys/prctl.h>
51 #include <sys/types.h>
53 #include <linux/futex.h>
54 #include <linux/filter.h>
55 #include <linux/seccomp.h>
61 #include <attribute.h>
63 #ifndef ARCH_CET_STATUS
64 #define ARCH_CET_STATUS 0x3001
67 static ATTRIBUTE_FORMAT_PRINTF (2, 3) _Noreturn
void
68 fail (int error
, const char *format
, ...)
71 va_start (ap
, format
);
72 vfprintf (stderr
, format
, ap
);
86 /* This binary is trivial, so we use a single global filter context
87 object that we release using `atexit'. */
89 static scmp_filter_ctx ctx
;
92 release_context (void)
94 seccomp_release (ctx
);
97 /* Wrapper functions and macros for libseccomp functions. We exit
98 immediately upon any error to avoid error checking noise. */
101 set_attribute (enum scmp_filter_attr attr
, uint32_t value
)
103 int status
= seccomp_attr_set (ctx
, attr
, value
);
105 fail (-status
, "seccomp_attr_set (ctx, %u, %u)", attr
, value
);
108 /* Like `seccomp_rule_add (ACTION, SYSCALL, ...)', except that you
109 don't have to specify the number of comparator arguments, and any
110 failure will exit the process. */
112 #define RULE(action, syscall, ...) \
115 const struct scmp_arg_cmp arg_array[] = {__VA_ARGS__}; \
116 enum { arg_cnt = sizeof arg_array / sizeof *arg_array }; \
117 int status = seccomp_rule_add_array (ctx, action, syscall, \
118 arg_cnt, arg_array); \
120 fail (-status, "seccomp_rule_add_array (%s, %s, %d, {%s})", \
121 #action, #syscall, arg_cnt, #__VA_ARGS__); \
126 export_filter (const char *file
,
127 int (*function
) (const scmp_filter_ctx
, int),
133 O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
| O_CLOEXEC
,
135 while (fd
< 0 && errno
== EINTR
);
137 fail (errno
, "open %s", file
);
138 int status
= function (ctx
, fd
);
140 fail (-status
, "%s", name
);
142 fail (errno
, "close");
145 #define EXPORT_FILTER(file, function) \
146 export_filter (file, function, #function)
149 main (int argc
, char **argv
)
152 fail (0, "usage: %s out.bpf out.pfc out-exec.bpf out-exec.pfc",
155 /* Any unhandled syscall should abort the Emacs process. */
156 ctx
= seccomp_init (SCMP_ACT_KILL_PROCESS
);
158 fail (0, "seccomp_init");
159 atexit (release_context
);
161 /* We want to abort immediately if the architecture is unknown. */
162 set_attribute (SCMP_FLTATR_ACT_BADARCH
, SCMP_ACT_KILL_PROCESS
);
163 set_attribute (SCMP_FLTATR_CTL_NNP
, 1);
164 set_attribute (SCMP_FLTATR_CTL_TSYNC
, 1);
166 static_assert (CHAR_BIT
== 8);
167 static_assert (sizeof (int) == 4 && INT_MIN
== INT32_MIN
168 && INT_MAX
== INT32_MAX
);
169 static_assert (sizeof (long) == 8 && LONG_MIN
== INT64_MIN
170 && LONG_MAX
== INT64_MAX
);
171 static_assert (sizeof (void *) == 8);
172 assert ((uintptr_t) NULL
== 0);
174 /* Allow a clean exit. */
175 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (exit
));
176 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (exit_group
));
178 /* Allow `mmap' and friends. This is necessary for dynamic loading,
179 reading the portable dump file, and thread creation. We don't
180 allow pages to be both writable and executable. */
181 static_assert (MAP_PRIVATE
!= 0);
182 static_assert (MAP_SHARED
!= 0);
183 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (mmap
),
184 SCMP_A2_32 (SCMP_CMP_MASKED_EQ
,
185 ~(PROT_NONE
| PROT_READ
| PROT_WRITE
)),
186 /* Only support known flags. MAP_DENYWRITE is ignored, but
187 some versions of the dynamic loader still use it. Also
188 allow allocating thread stacks. */
189 SCMP_A3_32 (SCMP_CMP_MASKED_EQ
,
190 ~(MAP_SHARED
| MAP_PRIVATE
| MAP_FILE
191 | MAP_ANONYMOUS
| MAP_FIXED
| MAP_DENYWRITE
192 | MAP_STACK
| MAP_NORESERVE
),
194 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (mmap
),
195 SCMP_A2_32 (SCMP_CMP_MASKED_EQ
,
196 ~(PROT_NONE
| PROT_READ
| PROT_EXEC
)),
197 /* Only support known flags. MAP_DENYWRITE is ignored, but
198 some versions of the dynamic loader still use it. */
199 SCMP_A3_32 (SCMP_CMP_MASKED_EQ
,
200 ~(MAP_PRIVATE
| MAP_ANONYMOUS
| MAP_FIXED
203 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (munmap
));
204 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (mprotect
),
205 /* Don't allow making pages executable. */
206 SCMP_A2_32 (SCMP_CMP_MASKED_EQ
,
207 ~(PROT_NONE
| PROT_READ
| PROT_WRITE
), 0));
209 /* Allow restartable sequences. The dynamic linker uses them. */
210 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (rseq
));
212 /* Futexes are used everywhere. */
213 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (futex
),
214 SCMP_A1_32 (SCMP_CMP_EQ
, FUTEX_WAKE_PRIVATE
));
216 /* Allow basic dynamic memory management. */
217 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (brk
));
219 /* Allow some status inquiries. */
220 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (uname
));
221 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getuid
));
222 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (geteuid
));
223 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getpid
));
224 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (gettid
));
225 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getpgrp
));
227 /* Allow operations on open file descriptors. File descriptors are
228 capabilities, and operating on them shouldn't cause security
230 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (read
));
231 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (pread64
));
232 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (write
));
233 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (close
));
234 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (lseek
));
235 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (dup
));
236 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (dup2
));
237 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (fstat
));
239 /* Allow read operations on the filesystem. If necessary, these
240 should be further restricted using mount namespaces. */
241 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (access
));
242 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (faccessat
));
243 #ifdef __NR_faccessat2
244 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (faccessat2
));
246 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (stat
));
247 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (stat64
));
248 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (lstat
));
249 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (lstat64
));
250 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (fstatat64
));
251 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (newfstatat
));
252 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (readlink
));
253 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (readlinkat
));
254 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getcwd
));
256 /* Allow opening files, assuming they are only opened for
258 static_assert (O_WRONLY
!= 0);
259 static_assert (O_RDWR
!= 0);
260 static_assert (O_CREAT
!= 0);
261 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (open
),
262 SCMP_A1_32 (SCMP_CMP_MASKED_EQ
,
263 ~(O_RDONLY
| O_BINARY
| O_CLOEXEC
| O_PATH
264 | O_DIRECTORY
| O_NOFOLLOW
),
266 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (openat
),
267 SCMP_A2_32 (SCMP_CMP_MASKED_EQ
,
268 ~(O_RDONLY
| O_BINARY
| O_CLOEXEC
| O_PATH
269 | O_DIRECTORY
| O_NOFOLLOW
),
272 /* Allow `tcgetpgrp'. */
273 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (ioctl
),
274 SCMP_A0_32 (SCMP_CMP_EQ
, STDIN_FILENO
),
275 SCMP_A1_32 (SCMP_CMP_EQ
, TIOCGPGRP
));
277 /* Allow reading (but not setting) file flags. */
278 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (fcntl
),
279 SCMP_A1_32 (SCMP_CMP_EQ
, F_GETFL
));
280 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (fcntl64
),
281 SCMP_A1_32 (SCMP_CMP_EQ
, F_GETFL
));
283 /* Allow reading random numbers from the kernel. */
284 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getrandom
));
286 /* Changing the umask is uncritical. */
287 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (umask
));
289 /* Allow creation of pipes. */
290 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (pipe
));
291 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (pipe2
));
293 /* Allow reading (but not changing) resource limits. */
294 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (getrlimit
));
295 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (prlimit64
),
296 SCMP_A0_32 (SCMP_CMP_EQ
, 0) /* pid == 0 (current process) */,
297 SCMP_A2_64 (SCMP_CMP_EQ
, 0) /* new_limit == NULL */);
299 /* Block changing resource limits, but don't crash. */
300 RULE (SCMP_ACT_ERRNO (EPERM
), SCMP_SYS (prlimit64
),
301 SCMP_A0_32 (SCMP_CMP_EQ
, 0) /* pid == 0 (current process) */,
302 SCMP_A2_64 (SCMP_CMP_NE
, 0) /* new_limit != NULL */);
304 /* Emacs installs signal handlers, which is harmless. */
305 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (sigaction
));
306 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (rt_sigaction
));
307 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (sigprocmask
));
308 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (rt_sigprocmask
));
310 /* Allow reading the current time. */
311 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (clock_gettime
),
312 SCMP_A0_32 (SCMP_CMP_EQ
, CLOCK_REALTIME
));
313 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (time
));
314 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (gettimeofday
));
316 /* Allow timer support. */
317 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (timer_create
));
318 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (timerfd_create
));
320 /* Allow thread creation. See the NOTES section in the manual page
321 for the `clone' function. */
322 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (clone
),
323 SCMP_A0_64 (SCMP_CMP_MASKED_EQ
,
324 /* Flags needed to create threads. See
325 create_thread in libc. */
326 ~(CLONE_VM
| CLONE_FS
| CLONE_FILES
327 | CLONE_SYSVSEM
| CLONE_SIGHAND
| CLONE_THREAD
328 | CLONE_SETTLS
| CLONE_PARENT_SETTID
329 | CLONE_CHILD_CLEARTID
),
331 /* glibc 2.34+ pthread_create uses clone3. */
332 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (clone3
));
333 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (sigaltstack
));
334 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (set_robust_list
));
336 /* Allow setting the process name for new threads. */
337 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (prctl
),
338 SCMP_A0_32 (SCMP_CMP_EQ
, PR_SET_NAME
));
340 /* Allow some event handling functions used by glib. */
341 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (eventfd
));
342 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (eventfd2
));
343 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (wait4
));
344 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (poll
));
345 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (pidfd_open
),
346 SCMP_A1_32 (SCMP_CMP_EQ
, 0));
348 /* Don't allow creating sockets (network access would be extremely
349 dangerous), but also don't crash. */
350 RULE (SCMP_ACT_ERRNO (EACCES
), SCMP_SYS (socket
));
352 EXPORT_FILTER (argv
[1], seccomp_export_bpf
);
353 EXPORT_FILTER (argv
[2], seccomp_export_pfc
);
355 /* When applying a Seccomp filter before executing the Emacs binary
356 (e.g. using the `bwrap' program), we need to allow further system
357 calls. Firstly, the wrapper binary will need to `execve' the
358 Emacs binary. Furthermore, the C library requires some system
359 calls at startup time to set up thread-local storage. */
360 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (execve
));
361 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (set_tid_address
));
362 RULE (SCMP_ACT_ERRNO (EINVAL
), SCMP_SYS (prctl
),
363 SCMP_A0_32 (SCMP_CMP_EQ
, PR_CAPBSET_READ
));
364 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (arch_prctl
),
365 SCMP_A0_32 (SCMP_CMP_EQ
, ARCH_SET_FS
));
366 RULE (SCMP_ACT_ERRNO (EINVAL
), SCMP_SYS (arch_prctl
),
367 SCMP_A0_32 (SCMP_CMP_EQ
, ARCH_CET_STATUS
));
368 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (statfs
));
370 /* We want to allow starting the Emacs binary itself with the
371 --seccomp flag, so we need to allow the `prctl' and `seccomp'
373 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (prctl
),
374 SCMP_A0_32 (SCMP_CMP_EQ
, PR_SET_NO_NEW_PRIVS
),
375 SCMP_A1_64 (SCMP_CMP_EQ
, 1), SCMP_A2_64 (SCMP_CMP_EQ
, 0),
376 SCMP_A3_64 (SCMP_CMP_EQ
, 0), SCMP_A4_64 (SCMP_CMP_EQ
, 0));
377 RULE (SCMP_ACT_ALLOW
, SCMP_SYS (seccomp
),
378 SCMP_A0_32 (SCMP_CMP_EQ
, SECCOMP_SET_MODE_FILTER
),
379 SCMP_A1_32 (SCMP_CMP_EQ
, SECCOMP_FILTER_FLAG_TSYNC
));
381 EXPORT_FILTER (argv
[3], seccomp_export_bpf
);
382 EXPORT_FILTER (argv
[4], seccomp_export_pfc
);