diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2016-12-06 17:03:17 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2016-12-08 17:06:41 +0100 |
commit | 95279b730a5c43a301d1e4d76d39e6e395f0a1c8 (patch) | |
tree | 04126281f09c03c88452f1f055fd065953a33b3c | |
parent | a381df112eb9b447b726544215599a5862fe8639 (diff) | |
download | tracker-95279b730a5c43a301d1e4d76d39e6e395f0a1c8.tar.gz |
libtracker-common: Implement sandboxing through libseccomp
The threads calling the new tracker_seccomp_init() function, and all
threads/processes spawned from these, will enter a restricted mode
where only a few sensible syscalls are allowed, and more specifically,
filesystem/socket access are restricted to being respectively
readonly and local only.
https://bugzilla.gnome.org/show_bug.cgi?id=764786
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | src/libtracker-common/Makefile.am | 2 | ||||
-rw-r--r-- | src/libtracker-common/tracker-common.h | 1 | ||||
-rw-r--r-- | src/libtracker-common/tracker-seccomp.c | 176 | ||||
-rw-r--r-- | src/libtracker-common/tracker-seccomp.h | 35 |
5 files changed, 234 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 8b5ad73a5..c2843d20e 100644 --- a/configure.ac +++ b/configure.ac @@ -2591,6 +2591,20 @@ fi AM_CONDITIONAL(HAVE_ARTWORK, test "x$have_artwork" = "xyes") +################################################################## +# Check for libseccomp +################################################################## + +PKG_CHECK_MODULES(LIBSECCOMP, + [libseccomp >= 2.0], + [have_libseccomp=yes], + [have_libseccomp=no]) + +if test "$have_libseccomp" = "yes"; then + LIBTRACKER_COMMON_LIBS="$LIBTRACKER_COMMON_LIBS $LIBSECCOMP_LIBS" + LIBTRACKER_COMMON_CFLAGS="$LIBTRACKER_COMMON_CFLAGS $LIBSECCOMP_CFLAGS" + AC_DEFINE(HAVE_LIBSECCOMP, [], [Define if we have libseccomp]) +fi ################################################################## # Write generated files @@ -2858,3 +2872,9 @@ WARNING: " fi + +if test "$have_libseccomp" = "no"; then +echo " +WARNING: libseccomp was not found, build will not be prevented, but this is a security flaw. +" +fi diff --git a/src/libtracker-common/Makefile.am b/src/libtracker-common/Makefile.am index 68422e932..4d2596e00 100644 --- a/src/libtracker-common/Makefile.am +++ b/src/libtracker-common/Makefile.am @@ -27,6 +27,7 @@ libtracker_common_la_SOURCES = \ tracker-ioprio.c \ tracker-log.c \ tracker-sched.c \ + tracker-seccomp.c \ tracker-type-utils.c \ tracker-utils.c \ tracker-locale.c \ @@ -42,6 +43,7 @@ noinst_HEADERS = \ tracker-date-time.h \ tracker-file-utils.h \ tracker-sched.h \ + tracker-seccomp.h \ tracker-type-utils.h \ tracker-utils.h \ tracker-locale.h \ diff --git a/src/libtracker-common/tracker-common.h b/src/libtracker-common/tracker-common.h index 1af7393f1..2434b7f08 100644 --- a/src/libtracker-common/tracker-common.h +++ b/src/libtracker-common/tracker-common.h @@ -36,6 +36,7 @@ #include "tracker-log.h" #include "tracker-parser.h" #include "tracker-sched.h" +#include "tracker-seccomp.h" #include "tracker-type-utils.h" #include "tracker-utils.h" #include "tracker-locale.h" diff --git a/src/libtracker-common/tracker-seccomp.c b/src/libtracker-common/tracker-seccomp.c new file mode 100644 index 000000000..3c3f449b7 --- /dev/null +++ b/src/libtracker-common/tracker-seccomp.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016, Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "tracker-seccomp.h" + +#ifdef HAVE_LIBSECCOMP + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/prctl.h> +#include <sys/syscall.h> +#include <sys/socket.h> +#include <fcntl.h> + +#include <seccomp.h> + +#define ALLOW_RULE(call) G_STMT_START { if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(call), 0) < 0) goto out; } G_STMT_END + +gboolean +tracker_seccomp_init (void) +{ + scmp_filter_ctx ctx; + + ctx = seccomp_init (SCMP_ACT_TRAP); + if (ctx == NULL) + return FALSE; + + /* Memory management */ + ALLOW_RULE (brk); + ALLOW_RULE (mmap); + ALLOW_RULE (munmap); + ALLOW_RULE (mremap); + ALLOW_RULE (mprotect); + ALLOW_RULE (madvise); + /* Process management */ + ALLOW_RULE (exit_group); + ALLOW_RULE (getuid); + ALLOW_RULE (geteuid); + ALLOW_RULE (getppid); + ALLOW_RULE (gettid); + ALLOW_RULE (exit); + /* Basic filesystem access */ + ALLOW_RULE (fstat); + ALLOW_RULE (stat); + ALLOW_RULE (statfs); + ALLOW_RULE (lstat); + ALLOW_RULE (access); + ALLOW_RULE (getdents); + ALLOW_RULE (readlink); + ALLOW_RULE (readlinkat); + ALLOW_RULE (utime); + ALLOW_RULE (fsync); + /* Processes and threads */ + ALLOW_RULE (clone); + ALLOW_RULE (futex); + ALLOW_RULE (set_robust_list); + ALLOW_RULE (rt_sigaction); + ALLOW_RULE (rt_sigprocmask); + ALLOW_RULE (sched_yield); + ALLOW_RULE (sched_getaffinity); + ALLOW_RULE (nanosleep); + /* Main loops */ + ALLOW_RULE (poll); + ALLOW_RULE (ppoll); + ALLOW_RULE (fcntl); + ALLOW_RULE (eventfd2); + ALLOW_RULE (pipe); + ALLOW_RULE (pipe2); + /* System */ + ALLOW_RULE (uname); + ALLOW_RULE (sysinfo); + ALLOW_RULE (prctl); + ALLOW_RULE (getrandom); + /* Descriptors */ + ALLOW_RULE (close); + ALLOW_RULE (read); + ALLOW_RULE (pread64); + ALLOW_RULE (lseek); + ALLOW_RULE (fadvise64); + ALLOW_RULE (write); + ALLOW_RULE (writev); + /* Needed by some GStreamer modules doing crazy stuff, less + * scary thanks to the restriction below about sockets being + * local. + */ + ALLOW_RULE (connect); + ALLOW_RULE (send); + ALLOW_RULE (sendto); + ALLOW_RULE (sendmsg); + ALLOW_RULE (recv); + ALLOW_RULE (recvmsg); + ALLOW_RULE (recvfrom); + ALLOW_RULE (getsockname); + ALLOW_RULE (getpeername); + ALLOW_RULE (shutdown); + + /* Special requirements for socket/socketpair, only on 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; + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, + SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) + goto out; + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, + SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 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; + + /* Special requirements for open, allow O_RDONLY calls, but fail + * if write permissions are requested. + */ + 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; + + g_debug ("Loading seccomp rules."); + + if (seccomp_load (ctx) >= 0) + return TRUE; + +out: + g_critical ("Failed to load seccomp rules."); + seccomp_release (ctx); + return FALSE; +} + +#else /* HAVE_LIBSECCOMP */ + +gboolean +tracker_seccomp_init (void) +{ + g_warning ("No seccomp support compiled-in."); + return TRUE; +} + +#endif /* HAVE_LIBSECCOMP */ diff --git a/src/libtracker-common/tracker-seccomp.h b/src/libtracker-common/tracker-seccomp.h new file mode 100644 index 000000000..0e0333024 --- /dev/null +++ b/src/libtracker-common/tracker-seccomp.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016, Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __TRACKER_SECCOMP_H__ +#define __TRACKER_SECCOMP_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) +#error "only <libtracker-common/tracker-common.h> must be included directly." +#endif + +gboolean tracker_seccomp_init (void); + +G_END_DECLS + +#endif /* __TRACKER_SECCOMP_H__ */ |