mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2025-01-13 20:15:59 +01:00
Merge branch 'master' into 'develop'
improve seccomp filter See merge request pwmt/zathura!53
This commit is contained in:
commit
07e9abc96b
3 changed files with 90 additions and 68 deletions
|
@ -11,6 +11,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <girara/utils.h>
|
||||
#include <linux/sched.h> /* for clone filter */
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gtk/gtkx.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define ADD_RULE(str_action, action, call, ...) \
|
||||
do { \
|
||||
|
@ -100,8 +106,12 @@ seccomp_enable_basic_filter(void)
|
|||
DENY_RULE(uselib);
|
||||
DENY_RULE(vmsplice);
|
||||
|
||||
/* TODO: check for additional syscalls to blacklist */
|
||||
/* DENY_RULE (execve); */
|
||||
/*TODO
|
||||
*
|
||||
* In case this basic filter is actually triggered, print a clear error message to report this
|
||||
* The syscalls here should never be executed by an unprivileged process
|
||||
*
|
||||
* */
|
||||
|
||||
/* applying filter... */
|
||||
if (seccomp_load(ctx) >= 0) {
|
||||
|
@ -117,7 +127,7 @@ out:
|
|||
}
|
||||
|
||||
int
|
||||
seccomp_enable_strict_filter(void)
|
||||
seccomp_enable_strict_filter(zathura_t* zathura)
|
||||
{
|
||||
/* prevent child processes from getting more priv e.g. via setuid, capabilities, ... */
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
|
@ -142,13 +152,11 @@ seccomp_enable_strict_filter(void)
|
|||
}
|
||||
|
||||
ALLOW_RULE(access);
|
||||
/* ALLOW_RULE (arch_prctl); */
|
||||
ALLOW_RULE(bind);
|
||||
ALLOW_RULE(brk);
|
||||
ALLOW_RULE(clock_getres);
|
||||
ALLOW_RULE(clone); /* TODO: investigate */
|
||||
/* ALLOW_RULE(clone); specified below */
|
||||
ALLOW_RULE(close);
|
||||
/* ALLOW_RULE (connect); */
|
||||
ALLOW_RULE(eventfd2);
|
||||
ALLOW_RULE(exit);
|
||||
ALLOW_RULE(exit_group);
|
||||
|
@ -170,14 +178,11 @@ seccomp_enable_strict_filter(void)
|
|||
ALLOW_RULE(getpid);
|
||||
ALLOW_RULE(getppid);
|
||||
ALLOW_RULE(gettid);
|
||||
/* ALLOW_RULE (getpeername); */
|
||||
ALLOW_RULE(getrandom);
|
||||
ALLOW_RULE(getresgid);
|
||||
ALLOW_RULE(getresuid);
|
||||
ALLOW_RULE(getrlimit);
|
||||
ALLOW_RULE(getpeername);
|
||||
/* ALLOW_RULE (getsockname); */
|
||||
/* ALLOW_RULE (getsockopt); needed for access to x11 socket in network namespace (without abstract sockets) */
|
||||
ALLOW_RULE(inotify_add_watch);
|
||||
ALLOW_RULE(inotify_init1);
|
||||
ALLOW_RULE(inotify_rm_watch);
|
||||
|
@ -186,7 +191,6 @@ seccomp_enable_strict_filter(void)
|
|||
ALLOW_RULE(lstat);
|
||||
ALLOW_RULE(madvise);
|
||||
ALLOW_RULE(memfd_create);
|
||||
ALLOW_RULE(mkdir); /* needed for first run only */
|
||||
ALLOW_RULE(mmap);
|
||||
ALLOW_RULE(mprotect);
|
||||
ALLOW_RULE(mremap);
|
||||
|
@ -197,9 +201,8 @@ seccomp_enable_strict_filter(void)
|
|||
ALLOW_RULE(pipe);
|
||||
ALLOW_RULE(pipe2);
|
||||
ALLOW_RULE(poll);
|
||||
ALLOW_RULE(pwrite64); /* TODO: build detailed filter */
|
||||
ALLOW_RULE(pwrite64);
|
||||
ALLOW_RULE(pread64);
|
||||
/* ALLOW_RULE (prlimit64); */
|
||||
/* ALLOW_RULE (prctl); specified below */
|
||||
ALLOW_RULE(read);
|
||||
ALLOW_RULE(readlink);
|
||||
|
@ -209,12 +212,12 @@ seccomp_enable_strict_filter(void)
|
|||
ALLOW_RULE(rseq);
|
||||
ALLOW_RULE(rt_sigaction);
|
||||
ALLOW_RULE(rt_sigprocmask);
|
||||
ALLOW_RULE(sched_setattr);
|
||||
ALLOW_RULE(sched_getattr);
|
||||
ALLOW_RULE(sendmsg);
|
||||
ALLOW_RULE(sendto);
|
||||
ALLOW_RULE(select);
|
||||
ALLOW_RULE(set_robust_list);
|
||||
/* ALLOW_RULE (set_tid_address); */
|
||||
/* ALLOW_RULE (setsockopt); */
|
||||
ALLOW_RULE(shmat);
|
||||
ALLOW_RULE(shmctl);
|
||||
ALLOW_RULE(shmdt);
|
||||
|
@ -223,30 +226,65 @@ seccomp_enable_strict_filter(void)
|
|||
ALLOW_RULE(stat);
|
||||
ALLOW_RULE(statx);
|
||||
ALLOW_RULE(statfs);
|
||||
/* ALLOW_RULE (socket); */
|
||||
ALLOW_RULE(sysinfo);
|
||||
ALLOW_RULE(umask); /* required by X11 */
|
||||
ALLOW_RULE(uname);
|
||||
ALLOW_RULE(unlink);
|
||||
ALLOW_RULE(write); /* specified below (zathura needs to write files)*/
|
||||
ALLOW_RULE(write);
|
||||
ALLOW_RULE(writev);
|
||||
ALLOW_RULE(wait4); /* trying to open links should not crash the app */
|
||||
|
||||
/* ADD_RULE("errno", SCMP_ACT_ERRNO(EPERM), sched_setattr, 0); */
|
||||
/* ADD_RULE("errno", SCMP_ACT_ERRNO(EPERM), sched_getattr, 0); */
|
||||
|
||||
/* required by glib */
|
||||
ALLOW_RULE(sched_setattr);
|
||||
ALLOW_RULE(sched_getattr);
|
||||
|
||||
/* required by some X11 setups */
|
||||
ADD_RULE("errno", SCMP_ACT_ERRNO(EPERM), umask, 0);
|
||||
ADD_RULE("errno", SCMP_ACT_ERRNO(EPERM), socket, 0);
|
||||
|
||||
ALLOW_RULE(wait4);
|
||||
|
||||
/* required for testing only */
|
||||
ALLOW_RULE(timer_create);
|
||||
ALLOW_RULE(timer_delete);
|
||||
|
||||
|
||||
/* Permit X11 specific syscalls */
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
GdkDisplay* display = gtk_widget_get_display(zathura->ui.session->gtk.view);
|
||||
|
||||
if (GDK_IS_X11_DISPLAY (display)) {
|
||||
|
||||
girara_debug("On X11, supporting X11 syscalls");
|
||||
|
||||
/* permit the socket syscall for local UNIX domain sockets (required by X11) */
|
||||
ADD_RULE("allow", SCMP_ACT_ALLOW, socket, 1, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX));
|
||||
|
||||
ALLOW_RULE(mkdir);
|
||||
ALLOW_RULE(setsockopt);
|
||||
ALLOW_RULE(connect);
|
||||
}
|
||||
else {
|
||||
girara_debug("On Wayland, blocking X11 syscalls");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* filter clone arguments */
|
||||
ADD_RULE("allow", SCMP_ACT_ALLOW, clone, 1, SCMP_CMP(0, SCMP_CMP_EQ, \
|
||||
CLONE_VM | \
|
||||
CLONE_FS | \
|
||||
CLONE_FILES | \
|
||||
CLONE_SIGHAND | \
|
||||
CLONE_THREAD | \
|
||||
CLONE_SYSVSEM | \
|
||||
CLONE_SETTLS | \
|
||||
CLONE_PARENT_SETTID | \
|
||||
CLONE_CHILD_CLEARTID));
|
||||
|
||||
|
||||
/* fcntl filter - not yet working */
|
||||
/*ADD_RULE("allow", SCMP_ACT_ALLOW, fcntl, 1, SCMP_CMP(0, SCMP_CMP_EQ, \
|
||||
F_GETFL | \
|
||||
F_SETFL | \
|
||||
F_ADD_SEALS | \
|
||||
F_SEAL_SEAL | \
|
||||
F_SEAL_SHRINK | \
|
||||
F_DUPFD_CLOEXEC | \
|
||||
F_SETFD | \
|
||||
FD_CLOEXEC )); */
|
||||
|
||||
|
||||
/* Special requirements for ioctl, allowed on stdout/stderr */
|
||||
ADD_RULE("allow", SCMP_ACT_ALLOW, ioctl, 1, SCMP_CMP(0, SCMP_CMP_EQ, 1));
|
||||
ADD_RULE("allow", SCMP_ACT_ALLOW, ioctl, 1, SCMP_CMP(0, SCMP_CMP_EQ, 2));
|
||||
|
@ -265,44 +303,26 @@ seccomp_enable_strict_filter(void)
|
|||
ADD_RULE("errno", SCMP_ACT_ERRNO(EACCES), openat, 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY));
|
||||
ADD_RULE("errno", SCMP_ACT_ERRNO(EACCES), openat, 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR));
|
||||
|
||||
/* allowed for debugging: */
|
||||
|
||||
/* ALLOW_RULE (prctl); */
|
||||
/* ALLOW_RULE (ioctl); */
|
||||
|
||||
/* TODO: test fcntl rules */
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, F_GETFL)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, F_SETFL)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, F_SETFD)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, F_GETFD)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, F_SETLK)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
|
||||
/* TODO: build detailed filter for prctl */
|
||||
/* needed by gtk??? (does not load content without) */
|
||||
|
||||
/* /\* special restrictions for prctl, only allow PR_SET_NAME/PR_SET_PDEATHSIG *\/ */
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_NAME)) < 0) */
|
||||
/* goto out; */
|
||||
/* Sandbox Status Notes:
|
||||
*
|
||||
* write: no actual files on the filesystem are opened with write permissions
|
||||
* exception is /run/user/UID/dconf/user (file descriptor not available during runtime)
|
||||
*
|
||||
*
|
||||
* mkdir: needed for first run only to create /run/user/UID/dconf (before seccomp init)
|
||||
* wait4: required to attempt opening links (which is then blocked)
|
||||
*
|
||||
* X11 environments require umask and socket syscalls after sandbox setup
|
||||
* no longer supported since X11 cannot be easily secured anyway
|
||||
*
|
||||
* TODO: prevent dbus socket connection before sandbox init - by checking the sandbox settings in zathurarc
|
||||
*
|
||||
* TODO: check requirement of pipe/pipe2 syscalls when dbus is disabled
|
||||
*/
|
||||
|
||||
/* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, */
|
||||
/* SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PDEATHSIG)) < 0) */
|
||||
/* goto out; */
|
||||
|
||||
/* when zathura is run on wayland, with X11 server available but blocked, unset the DISPLAY variable */
|
||||
/* otherwise it will try to connect to X11 using inet socket protocol */
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef ZATHURA_SECCOMP_FILTERS_H
|
||||
#define ZATHURA_SECCOMP_FILTERS_H
|
||||
|
||||
#include "zathura.h"
|
||||
|
||||
/* basic filter */
|
||||
/* this mode allows normal use */
|
||||
/* only dangerous syscalls are blacklisted */
|
||||
|
@ -10,6 +12,6 @@ int seccomp_enable_basic_filter(void);
|
|||
|
||||
/* strict filter before document parsing */
|
||||
/* this filter is to be enabled after most of the initialisation of zathura has finished */
|
||||
int seccomp_enable_strict_filter(void);
|
||||
int seccomp_enable_strict_filter(zathura_t* zathura);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -451,7 +451,7 @@ zathura_init(zathura_t* zathura)
|
|||
break;
|
||||
case ZATHURA_SANDBOX_STRICT:
|
||||
girara_debug("Strict sandbox preventing write and network access.");
|
||||
if (seccomp_enable_strict_filter() != 0) {
|
||||
if (seccomp_enable_strict_filter(zathura) != 0) {
|
||||
girara_error("Failed to initialize strict seccomp filter.");
|
||||
goto error_free;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue