diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | xdg-app-helper.c | 110 |
3 files changed, 111 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am index f593dd5..7e18e04 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,7 +40,8 @@ include libglnx/Makefile-libglnx.am.inc noinst_LTLIBRARIES = libglnx.la xdg_app_helper_SOURCES = xdg-app-helper.c -xdg_app_helper_LDADD = -L/gnome/lib -lglib-2.0 +xdg_app_helper_LDADD = $(LIBSECCOMP_LIBS) +xdg_app_helper_CFLAGS = $(LIBSECCOMP_CFLAGS) dbus_built_sources = xdg-app-dbus.c xdg-app-dbus.h systemd_dbus_built_sources = xdg-app-systemd-dbus.c xdg-app-systemd-dbus.h diff --git a/configure.ac b/configure.ac index b85b678..e093230 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,9 @@ AC_SUBST(BASE_LIBS) PKG_CHECK_MODULES(SOUP, [libsoup-2.4]) AC_SUBST(SOUP_CFLAGS) AC_SUBST(SOUP_LIBS) +PKG_CHECK_MODULES(LIBSECCOMP, [libseccomp]) +AC_SUBST(LIBSECCOMP_CFLAGS) +AC_SUBST(LIBSECCOMP_LIBS) PKG_CHECK_MODULES(OSTREE, [libgsystem >= 2015.1 ostree-1 >= 2015.3]) AC_SUBST(OSTREE_CFLAGS) AC_SUBST(OSTREE_LIBS) diff --git a/xdg-app-helper.c b/xdg-app-helper.c index 0b0dbd0..eea03aa 100644 --- a/xdg-app-helper.c +++ b/xdg-app-helper.c @@ -48,6 +48,8 @@ #include <sys/prctl.h> #include <unistd.h> +#include <seccomp.h> + #if 0 #define __debug__(x) printf x #else @@ -98,12 +100,18 @@ die (const char *format, ...) exit (1); } +static void +die_oom (void) +{ + die ("Out of memory"); +} + static void * xmalloc (size_t size) { void *res = malloc (size); if (res == NULL) - die ("oom"); + die_oom (); return res; } @@ -112,7 +120,7 @@ xrealloc (void *ptr, size_t size) { void *res = realloc (ptr, size); if (size != 0 && res == NULL) - die ("oom"); + die_oom (); return res; } @@ -125,7 +133,7 @@ xstrdup (const char *str) res = strdup (str); if (res == NULL) - die ("oom"); + die_oom (); return res; } @@ -205,7 +213,7 @@ strdup_printf (const char *format, va_end (args); if (buffer == NULL) - die ("oom"); + die_oom (); return buffer; } @@ -274,6 +282,97 @@ static inline int raw_clone(unsigned long flags, void *child_stack) { } static void +setup_seccomp (void) +{ + scmp_filter_ctx seccomp; + struct { + int scall; + struct scmp_arg_cmp *arg; + } syscall_blacklist[] = { + /* Block dmesg */ + {SCMP_SYS(syslog)}, + /* Useless old syscall */ + {SCMP_SYS(uselib)}, + /* Don't allow you to switch to bsd emulation or whatnot */ + {SCMP_SYS(personality)}, + /* Don't allow disabling accounting */ + {SCMP_SYS(acct)}, + /* 16-bit code is unnecessary in the sandbox, and modify_ldt is a + historic source of interesting information leaks. */ + {SCMP_SYS(modify_ldt)}, + /* Don't allow reading current quota use */ + {SCMP_SYS(quotactl)}, + + /* Scary VM/NUMA ops */ + {SCMP_SYS(move_pages)}, + {SCMP_SYS(mbind)}, + {SCMP_SYS(get_mempolicy)}, + {SCMP_SYS(set_mempolicy)}, + {SCMP_SYS(migrate_pages)}, + + /* Don't allow subnamespace setups: */ + {SCMP_SYS(unshare)}, + {SCMP_SYS(mount)}, + {SCMP_SYS(pivot_root)}, + {SCMP_SYS(clone), &SCMP_A0(SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)} + }; + /* Blacklist all but unix, inet, inet6 and netlink */ + int socket_family_blacklist[] = { + AF_AX25, + AF_IPX, + AF_APPLETALK, + AF_NETROM, + AF_BRIDGE, + AF_ATMPVC, + AF_X25, + AF_ROSE, + AF_DECnet, + AF_NETBEUI, + AF_SECURITY, + AF_KEY, + AF_NETLINK + 1, /* Last gets CMP_GE, so order is important */ + }; + int i, r; + + seccomp = seccomp_init(SCMP_ACT_ALLOW); + if (!seccomp) + return die_oom (); + + /* TODO: Should we filter the kernel keyring syscalls in some way? + * We do want them to be used by desktop apps, but they could also perhaps + * leak system stuff or secrets from other apps. + */ + + for (i = 0; i < N_ELEMENTS (syscall_blacklist); i++) + { + int scall = syscall_blacklist[i].scall; + if (syscall_blacklist[i].arg) + r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 1, *syscall_blacklist[i].arg); + else + r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 0); + if (r < 0 && r == -EFAULT /* unknown syscall */) + die_with_error ("Failed to block syscall %d", scall); + } + + for (i = 0; i < N_ELEMENTS (socket_family_blacklist); i++) + { + int family = socket_family_blacklist[i]; + if (i == N_ELEMENTS (socket_family_blacklist) - 1) + r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, family)); + else + r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_GE, family)); + if (r < 0) + die_with_error ("Failed to block socket family %d", family); + } + + r = seccomp_load (seccomp); + if (r < 0) + die_with_error ("Failed to install seccomp audit filter: "); + + seccomp_release (seccomp); +} + +static void usage (char **argv) { fprintf (stderr, "usage: %s [OPTIONS...] RUNTIMEPATH COMMAND [ARGS...]\n\n", argv[0]); @@ -2084,6 +2183,9 @@ main (int argc, } #endif + __debug__(("setting up seccomp\n")); + setup_seccomp (); + __debug__(("forking for child\n")); pid = fork (); |