From 4bde3d793ff25f0b158ca1f5fd6ebc60c23b4d05 Mon Sep 17 00:00:00 2001 From: valoq Date: Sat, 30 Dec 2017 13:46:07 +0100 Subject: [PATCH] seccomp implementation --- Makefile | 4 + config.mk | 12 + zathura/libsec.c | 554 +++++++++++++++++++++++++++++++++++++++++++++++ zathura/libsec.h | 19 ++ zathura/links.c | 9 + zathura/main.c | 15 ++ 6 files changed, 613 insertions(+) create mode 100644 zathura/libsec.c create mode 100644 zathura/libsec.h diff --git a/Makefile b/Makefile index 9a22c30..8eda173 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,10 @@ ifneq ($(WITH_SYNCTEX),0) CPPFLAGS += -DWITH_SYNCTEX endif +ifneq ($(WITH_SECCOMP),0) +CPPFLAGS += -DWITH_SECCOMP +endif + ifneq ($(wildcard ${VALGRIND_SUPPRESSION_FILE}),) VALGRIND_ARGUMENTS += --suppressions=${VALGRIND_SUPPRESSION_FILE} endif diff --git a/config.mk b/config.mk index 7a488cf..b7f55d3 100644 --- a/config.mk +++ b/config.mk @@ -47,6 +47,10 @@ WITH_SYNCTEX ?= $(shell (${PKG_CONFIG} synctex && echo 1) || echo 0) # To disable support for mimetype detction with libmagic set WITH_MAGIC to 0. WITH_MAGIC ?= 1 +# seccomp +# To enable support for seccomp filter set WITH_SECCOMP to 1. +WITH_SECCOMP ?= 0 + # paths PREFIX ?= /usr MANPREFIX ?= ${PREFIX}/share/man @@ -116,6 +120,14 @@ LIBS += ${SYNCTEX_LIB} endif endif +ifneq (${WITH_SECCOMP},0) +SECCOMP_INC ?= +SECCOMP_LIB ?= -lseccomp + +INCS += ${SECCOMP_INC} +LIBS += ${SECCOMP_LIB} +endif + ifneq (${PKG_CONFIG_LIBS},) INCS += $(shell ${PKG_CONFIG} --cflags ${PKG_CONFIG_LIBS}) LIBS += $(shell ${PKG_CONFIG} --libs ${PKG_CONFIG_LIBS}) diff --git a/zathura/libsec.c b/zathura/libsec.c new file mode 100644 index 0000000..ed87142 --- /dev/null +++ b/zathura/libsec.c @@ -0,0 +1,554 @@ +#include "libsec.h" +#include + +#ifdef WITH_SECCOMP + +#include /* libseccomp */ +#include /* prctl */ +#include +#include +#include +#include + +#define DENY_RULE(call) { if (seccomp_rule_add (ctx, SCMP_ACT_KILL, SCMP_SYS(call), 0) < 0) goto out; } +#define ALLOW_RULE(call) { if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(call), 0) < 0) goto out; } + +scmp_filter_ctx ctx; + + + +int protectedMode(void){ + + /* prevent child processes from getting more priv e.g. via setuid, capabilities, ... */ + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl SET_NO_NEW_PRIVS"); + exit(EXIT_FAILURE); + } + + /* prevent escape via ptrace */ + if(prctl (PR_SET_DUMPABLE, 0, 0, 0, 0)){ + perror("prctl PR_SET_DUMPABLE"); + exit(EXIT_FAILURE); + } + + /* initialize the filter */ + ctx = seccomp_init(SCMP_ACT_ALLOW); + if (ctx == NULL){ + perror("seccomp_init failed"); + exit(EXIT_FAILURE); + } + + + DENY_RULE (_sysctl); + DENY_RULE (acct); + DENY_RULE (add_key); + DENY_RULE (adjtimex); + DENY_RULE (chroot); + DENY_RULE (clock_adjtime); + DENY_RULE (create_module); + DENY_RULE (delete_module); + DENY_RULE (fanotify_init); + DENY_RULE (finit_module); + DENY_RULE (get_kernel_syms); + DENY_RULE (get_mempolicy); + DENY_RULE (init_module); + DENY_RULE (io_cancel); + DENY_RULE (io_destroy); + DENY_RULE (io_getevents); + DENY_RULE (io_setup); + DENY_RULE (io_submit); + DENY_RULE (ioperm); + DENY_RULE (iopl); + DENY_RULE (ioprio_set); + DENY_RULE (kcmp); + DENY_RULE (kexec_file_load); + DENY_RULE (kexec_load); + DENY_RULE (keyctl); + DENY_RULE (lookup_dcookie); + DENY_RULE (mbind); + DENY_RULE (nfsservctl); + DENY_RULE (migrate_pages); + DENY_RULE (modify_ldt); + DENY_RULE (mount); + DENY_RULE (move_pages); + DENY_RULE (name_to_handle_at); + DENY_RULE (open_by_handle_at); + DENY_RULE (perf_event_open); + DENY_RULE (pivot_root); + DENY_RULE (process_vm_readv); + DENY_RULE (process_vm_writev); + DENY_RULE (ptrace); + DENY_RULE (reboot); + DENY_RULE (remap_file_pages); + DENY_RULE (request_key); + DENY_RULE (set_mempolicy); + DENY_RULE (swapoff); + DENY_RULE (swapon); + DENY_RULE (sysfs); + DENY_RULE (syslog); + DENY_RULE (tuxcall); + DENY_RULE (umount2); + DENY_RULE (uselib); + DENY_RULE (vmsplice); + + + /* applying filter... */ + if (seccomp_load (ctx) >= 0){ + /* free ctx after the filter has been loaded into the kernel */ + seccomp_release(ctx); + return 0; + } + + out: + /* something went wrong */ + seccomp_release(ctx); + return 1; + +} + + +int protectedView(void){ + + /* prevent child processes from getting more priv e.g. via setuid, capabilities, ... */ + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl SET_NO_NEW_PRIVS"); + exit(EXIT_FAILURE); + } + + /* prevent escape via ptrace */ + if(prctl (PR_SET_DUMPABLE, 0, 0, 0, 0)){ + perror("prctl PR_SET_DUMPABLE"); + exit(EXIT_FAILURE); + } + + /* initialize the filter */ + ctx = seccomp_init(SCMP_ACT_KILL); + if (ctx == NULL){ + perror("seccomp_init failed"); + exit(EXIT_FAILURE); + } + + + ALLOW_RULE (access); + ALLOW_RULE (bind); + ALLOW_RULE (brk); + ALLOW_RULE (clock_getres); + ALLOW_RULE (clone); + ALLOW_RULE (close); + ALLOW_RULE (connect); + ALLOW_RULE (eventfd2); + ALLOW_RULE (exit); + ALLOW_RULE (exit_group); + ALLOW_RULE (fadvise64); + ALLOW_RULE (fallocate); + ALLOW_RULE (fcntl); /* TODO: build detailed filter */ + ALLOW_RULE (fstat); + ALLOW_RULE (fstatfs); + ALLOW_RULE (ftruncate); + ALLOW_RULE (futex); + ALLOW_RULE (getdents); + ALLOW_RULE (getegid); + ALLOW_RULE (geteuid); + ALLOW_RULE (getgid); + ALLOW_RULE (getuid); + ALLOW_RULE (getpid); + ALLOW_RULE (getppid); + ALLOW_RULE (getpgrp); + ALLOW_RULE (getpeername); + ALLOW_RULE (getrandom); + ALLOW_RULE (getresgid); + ALLOW_RULE (getresuid); + ALLOW_RULE (getrlimit); + 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); + /* ALLOW_RULE (ioctl); specified below */ + ALLOW_RULE (lseek); + 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); + ALLOW_RULE (munmap); + ALLOW_RULE (open); /* (zathura needs to open for writing) TODO: avoid needing this somehow */ + ALLOW_RULE (openat); + ALLOW_RULE (pipe); + ALLOW_RULE (poll); + ALLOW_RULE (pwrite64); /* TODO: build detailed filter */ + ALLOW_RULE (pread64); + ALLOW_RULE (prlimit64); + ALLOW_RULE (prctl); /* NOT specified below */ + ALLOW_RULE (read); + ALLOW_RULE (readlink); + ALLOW_RULE (recvfrom); + ALLOW_RULE (recvmsg); + ALLOW_RULE (restart_syscall); + ALLOW_RULE (rt_sigaction); + ALLOW_RULE (rt_sigprocmask); + ALLOW_RULE (seccomp); + ALLOW_RULE (sendmsg); + ALLOW_RULE (sendto); + ALLOW_RULE (select); + ALLOW_RULE (set_robust_list); + ALLOW_RULE (setsockopt); + ALLOW_RULE (shmat); + ALLOW_RULE (shmctl); + ALLOW_RULE (shmdt); + ALLOW_RULE (shmget); + ALLOW_RULE (shutdown); + ALLOW_RULE (stat); + ALLOW_RULE (statfs); + /* ALLOW_RULE (socket); specified below */ + ALLOW_RULE (sysinfo); + ALLOW_RULE (uname); + ALLOW_RULE (unlink); + ALLOW_RULE (write); /* specified below (zathura needs to write files)*/ + ALLOW_RULE (writev); + ALLOW_RULE (wait4); /* trying to open links should not crash the app */ + + + /* allowed for use with container */ + + ALLOW_RULE (chmod); + ALLOW_RULE (link); + ALLOW_RULE (rename); + + + + /* allowed for debugging: */ + + /* ALLOW_RULE (prctl); */ + /* ALLOW_RULE (ioctl); */ + + + + /* incomplete */ + + /* 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; */ + + + /* Special requirements for ioctl, allowed on stdout/stderr */ + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0) + goto out; + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 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; */ + + /* 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 */ + + /* required changes in links.c (at girara_xdg_open) */ + /* special restrictions for socket, only allow AF_UNIX/AF_LOCAL */ + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, + SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) + goto out; + + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, + SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0) + goto out; + + + + /* TODO: avoid the need for the open syscall to be allowed with write permissions */ + + /* zathura needs to open files for writing to save current position */ + + /* /\* special restrictions for open, prevent opening files for writing *\/ */ + /* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, */ + /* SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0) */ + /* goto out; */ + + /* if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, */ + /* SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0) */ + /* goto out; */ + + /* if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, */ + /* SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) < 0) */ + /* goto out; */ + + + + + + /* ------------ experimental filters --------------- */ + + + /* /\* this filter is susceptible to TOCTOU race conditions, providing limited use *\/ */ + /* /\* allow opening only specified files identified by their file descriptors*\/ */ + + /* this requires either a list of all files to open (A LOT!!!) */ + /* or needs to be applied only after initialisation, right before parsing */ + /* if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1, */ + /* SCMP_CMP(SCMP_CMP_EQ, fd)) < 0) /\* or < 1 ??? *\/ */ + /* goto out; */ + + + /* /\* restricting write access *\/ */ + + /* /\* allow stdin *\/ */ + /* if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, */ + /* SCMP_CMP(0, SCMP_CMP_EQ, 0)) < 0 ) */ + /* goto out; */ + + /* /\* allow stdout *\/ */ + /* if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, */ + /* SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0 ) */ + /* goto out; */ + + + /* /\* allow stderr *\/ */ + /* if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, */ + /* SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 0 ) */ + /* goto out; */ + + + /* /\* restrict writev (write a vector) access *\/ */ + /* this does not seem reliable but it surprisingly is. investigate more */ + /* if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, */ + /* SCMP_CMP(0, SCMP_CMP_EQ, 3)) < 0 ) */ + /* goto out; */ + + /* test if repeating this after some time or denying it works */ + + + /* first attempt to filter poll requests */ + /* if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 1, */ + /* SCMP_CMP(0, SCMP_CMP_MASKED_EQ, POLLIN | POLL, 0)) < 0) */ + /* goto out; */ + + + /* /\* restrict fcntl calls *\/ */ + /* this syscall sets the file descriptor to read write */ + /* if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1, */ + /* SCMP_CMP(0, SCMP_CMP_EQ, 3)) < 0 ) */ + /* goto out; */ + /* fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) */ + /* fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 */ + /* fcntl(3, F_SETFD, FD_CLOEXEC) = 0 */ + + + /* ------------------ end of experimental filters ------------------ */ + + + /* applying filter... */ + if (seccomp_load (ctx) >= 0){ + /* free ctx after the filter has been loaded into the kernel */ + seccomp_release(ctx); + return 0; + } + + out: + /* something went wrong */ + seccomp_release(ctx); + return 1; + + +} + + +int strictFilter(void){ + + /* prevent child processes from getting more priv e.g. via setuid, capabilities, ... */ + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl SET_NO_NEW_PRIVS"); + exit(EXIT_FAILURE); + } + + /* prevent escape via ptrace */ + if(prctl (PR_SET_DUMPABLE, 0, 0, 0, 0)){ + perror("prctl PR_SET_DUMPABLE"); + exit(EXIT_FAILURE); + } + + /* initialize the filter */ + ctx = seccomp_init(SCMP_ACT_KILL); + if (ctx == NULL){ + perror("seccomp_init failed"); + exit(EXIT_FAILURE); + } + + + ALLOW_RULE (access); + /* ALLOW_RULE (arch_prctl); */ + ALLOW_RULE (bind); + ALLOW_RULE (brk); + ALLOW_RULE (clock_getres); + ALLOW_RULE (clone); + ALLOW_RULE (close); + /* ALLOW_RULE (connect); */ + ALLOW_RULE (eventfd2); + ALLOW_RULE (exit); + ALLOW_RULE (exit_group); + ALLOW_RULE (fadvise64); + ALLOW_RULE (fallocate); + ALLOW_RULE (fcntl); /* TODO: build detailed filter */ + ALLOW_RULE (fstat); + ALLOW_RULE (fstatfs); + ALLOW_RULE (ftruncate); + ALLOW_RULE (futex); + ALLOW_RULE (getdents); + ALLOW_RULE (getegid); + ALLOW_RULE (geteuid); + ALLOW_RULE (getgid); + ALLOW_RULE (getuid); + ALLOW_RULE (getpid); + /* ALLOW_RULE (getpeername); */ + ALLOW_RULE (getresgid); + ALLOW_RULE (getresuid); + ALLOW_RULE (getrlimit); + /* 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); + /* ALLOW_RULE (ioctl); specified below */ + ALLOW_RULE (lseek); + 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); + ALLOW_RULE (munmap); + ALLOW_RULE (open); /* (zathura needs to open for writing) TODO: avoid needing this somehow */ + ALLOW_RULE (openat); + ALLOW_RULE (pipe); + ALLOW_RULE (poll); + ALLOW_RULE (pwrite64); /* TODO: build detailed filter */ + ALLOW_RULE (pread64); + /* ALLOW_RULE (prlimit64); */ + /* ALLOW_RULE (prctl); specified below */ + ALLOW_RULE (read); + ALLOW_RULE (readlink); + ALLOW_RULE (recvfrom); + ALLOW_RULE (recvmsg); + ALLOW_RULE (restart_syscall); + ALLOW_RULE (rt_sigaction); + ALLOW_RULE (rt_sigprocmask); + 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); + ALLOW_RULE (shmget); + ALLOW_RULE (shutdown); + ALLOW_RULE (stat); + ALLOW_RULE (statfs); + /* ALLOW_RULE (socket); */ + ALLOW_RULE (sysinfo); + ALLOW_RULE (uname); + ALLOW_RULE (unlink); + ALLOW_RULE (write); /* specified below (zathura needs to write files)*/ + ALLOW_RULE (writev); + ALLOW_RULE (wait4); /* trying to open links should not crash the app */ + + + /* Special requirements for ioctl, allowed on stdout/stderr */ + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0) + goto out; + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 0) + goto out; + + + + /* 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; + + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PDEATHSIG)) < 0) + goto out; + + + + /* allowed for debugging: */ + + /* ALLOW_RULE (prctl); */ + /* ALLOW_RULE (ioctl); */ + + + /* applying filter... */ + if (seccomp_load (ctx) >= 0){ + /* free ctx after the filter has been loaded into the kernel */ + seccomp_release(ctx); + return 0; + } + + out: + /* something went wrong */ + seccomp_release(ctx); + return 1; +} + + +#else /* WITH_SECCOMP */ + +int protectedMode(void){ + + perror("No seccomp support compiled-in\n"); + return 1; +} + +int protectedView(void){ + + perror("No seccomp support compiled-in\n"); + return 1; +} + +int strictFilter(void){ + + perror("No seccomp support compiled-in\n"); + return 1; +} + +#endif /* WITH_SECCOMP */ diff --git a/zathura/libsec.h b/zathura/libsec.h new file mode 100644 index 0000000..2b604df --- /dev/null +++ b/zathura/libsec.h @@ -0,0 +1,19 @@ +#ifndef SECCOMP_H +#define SECCOMP_H + +/* basic filter */ +/* this mode allows normal use */ +/* only dangerous syscalls are blacklisted */ +int protectedMode(void); + +/* secure whitelist filter */ +/* whitelist minimal syscalls only */ +/* this mode does not allow to open external links or to start applications */ +/* network connections are prohibited as well */ +int protectedView(void); + +/* strict filter before document parsing */ +/* this filter is to be enabled after most of the initialisation of zathura has finished */ +int strictFilter(void); + +#endif diff --git a/zathura/links.c b/zathura/links.c index 47030e2..6eeb0dd 100644 --- a/zathura/links.c +++ b/zathura/links.c @@ -14,6 +14,10 @@ #include "page.h" #include "render.h" +#ifdef WITH_SECCOMP +#include "libsec.h" +#endif + struct zathura_link_s { zathura_rectangle_t position; /**< Position of the link */ zathura_link_type_t type; /**< Link type */ @@ -199,9 +203,14 @@ zathura_link_evaluate(zathura_t* zathura, zathura_link_t* link) link_remote(zathura, link->target.value); break; case ZATHURA_LINK_URI: +#ifndef WITH_SECCOMP if (girara_xdg_open(link->target.value) == false) { girara_notify(zathura->ui.session, GIRARA_ERROR, _("Failed to run xdg-open.")); } +#endif +#ifdef WITH_SECCOMP + girara_notify(zathura->ui.session, GIRARA_ERROR, _("Opening external apps in protectedView Sandbox mode is not permitted")); +#endif break; case ZATHURA_LINK_LAUNCH: link_launch(zathura, link); diff --git a/zathura/main.c b/zathura/main.c index 2355a1e..2c8e31a 100644 --- a/zathura/main.c +++ b/zathura/main.c @@ -19,6 +19,11 @@ #include "synctex.h" #endif +#ifdef WITH_SECCOMP +#include +#include "libsec.h" +#endif + /* Init locale */ static void init_locale(void) @@ -122,6 +127,11 @@ init_zathura(const char* config_dir, const char* data_dir, int main(int argc, char* argv[]) { + +#ifdef WITH_SECCOMP + protectedView(); +#endif + init_locale(); /* parse command line arguments */ @@ -288,6 +298,11 @@ main(int argc, char* argv[]) goto free_and_ret; } +#ifdef WITH_SECCOMP + /* enforce strict syscall filter before parsing the document */ + strictFilter(); +#endif + /* open document if passed */ if (file_idx != 0) { if (page_number > 0) {