diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-10-19 20:28:57 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-10-19 21:29:11 +0100 |
commit | 9e74a6dc5a2bdca647b3ccc129af41fb1a543483 (patch) | |
tree | a416fdd13fe845d6d0790c4828faf0ba38353324 | |
parent | fe1b7da17caa0f0e9909aed56061ab9c9f803a4d (diff) | |
download | tracker-wip/sam/meson-subproject.tar.gz |
libtracker-common: Add tracker-seccomp from the libtracker-miners librarywip/sam/meson-subproject
This module is only used in the tracker-miners repo. However, when
building this repo as a Meson subproject of tracker-miners.git, we
can only build one version of libtracker-common so we need to have
it present in our version.
-rw-r--r-- | config.h.meson.in | 3 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | src/libtracker-common/meson.build | 8 | ||||
-rw-r--r-- | src/libtracker-common/tracker-seccomp.c | 228 | ||||
-rw-r--r-- | src/libtracker-common/tracker-seccomp.h | 35 |
5 files changed, 275 insertions, 1 deletions
diff --git a/config.h.meson.in b/config.h.meson.in index 25d292062..e3cab84ca 100644 --- a/config.h.meson.in +++ b/config.h.meson.in @@ -69,6 +69,9 @@ /* Define if we have libiptcdata */ #mesondefine HAVE_LIBIPTCDATA +/* Define if we have libseccomp */ +#mesondefine HAVE_LIBSECCOMP +# /* Define if we have libstemmer */ #mesondefine HAVE_LIBSTEMMER diff --git a/meson.build b/meson.build index 976fa154f..86e150ba8 100644 --- a/meson.build +++ b/meson.build @@ -26,6 +26,7 @@ gobject_introspection = dependency('gobject-introspection-1.0') icu_i18n = dependency('icu-i18n', version: '> 4.8.1.1', required: false) icu_uc = dependency('icu-uc', version: '> 4.8.1.1', required: false) json_glib = dependency('json-glib-1.0', version: '>= 1.0', required: true) +libseccomp = dependency('libseccomp', version: '>= 2.0', required: false) libsoup = dependency('libsoup-2.4', version: '> 2.40', required: true) libxml2 = dependency('libxml-2.0', version: '> 2.6') network_manager = dependency('libnm', required: false) @@ -230,6 +231,7 @@ conf.set('HAVE_BUILTIN_FTS', sqlite3_has_builtin_fts5) conf.set('HAVE_ENCA', charset_library_name == 'enca') conf.set10('HAVE_LIBICU', unicode_library_name == 'icu') conf.set('HAVE_LIBICU_CHARSET_DETECTION', charset_library_name == 'icu') +conf.set('HAVE_LIBSECCOMP', libseccomp.found()) conf.set('HAVE_LIBSTEMMER', have_libstemmer) conf.set('HAVE_LIBUNISTRING', unicode_library_name == 'unistring') conf.set('HAVE_NETWORK_MANAGER', network_manager.found()) diff --git a/src/libtracker-common/meson.build b/src/libtracker-common/meson.build index c9a1defb9..9f5106650 100644 --- a/src/libtracker-common/meson.build +++ b/src/libtracker-common/meson.build @@ -26,6 +26,7 @@ tracker_common_sources = [ 'tracker-locale.c', 'tracker-parser-utils.c', 'tracker-language.c', + 'tracker-seccomp.c', enums[0], enums[1], tracker_common_parser_sha1_header, ] @@ -39,9 +40,14 @@ endif # FIXME: need to link against -lkvm on OpenBSD, see configure.ac tracker_common_dependencies = [glib, gio, gio_unix, libmath] +tracker_common_private_dependencies = [unicode_library] +if libseccomp.found() + tracker_common_private_dependencies += [libseccomp] +endif + libtracker_common = library('tracker-common', tracker_common_sources, - dependencies: tracker_common_dependencies + [unicode_library], + dependencies: tracker_common_dependencies + tracker_common_private_dependencies, c_args: tracker_c_args, include_directories: [configinc, srcinc], install: true, diff --git a/src/libtracker-common/tracker-seccomp.c b/src/libtracker-common/tracker-seccomp.c new file mode 100644 index 000000000..ec873f5e0 --- /dev/null +++ b/src/libtracker-common/tracker-seccomp.c @@ -0,0 +1,228 @@ +/* + * 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 { \ + int allow_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ + if (allow_rule_syscall_number == __NR_SCMP_ERROR || \ + seccomp_rule_add (ctx, SCMP_ACT_ALLOW, allow_rule_syscall_number, 0) < 0) \ + goto out; \ +} G_STMT_END + +#define ERROR_RULE(call, error) G_STMT_START { \ + int error_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ + if (error_rule_syscall_number == __NR_SCMP_ERROR || \ + seccomp_rule_add (ctx, SCMP_ACT_ERRNO (error), error_rule_syscall_number, 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 (mmap2); + ALLOW_RULE (munmap); + ALLOW_RULE (mremap); + ALLOW_RULE (mprotect); + ALLOW_RULE (madvise); + ERROR_RULE (mlock, EPERM); + ERROR_RULE (mlock2, EPERM); + ERROR_RULE (munlock, EPERM); + ERROR_RULE (mlockall, EPERM); + ERROR_RULE (munlockall, EPERM); + /* Process management */ + ALLOW_RULE (exit_group); + ALLOW_RULE (getuid); + ALLOW_RULE (getuid32); + ALLOW_RULE (geteuid); + ALLOW_RULE (geteuid32); + ALLOW_RULE (getppid); + ALLOW_RULE (gettid); + ALLOW_RULE (getpid); + ALLOW_RULE (exit); + ALLOW_RULE (getrusage); + ALLOW_RULE (getrlimit); + /* Basic filesystem access */ + ALLOW_RULE (fstat); + ALLOW_RULE (fstat64); + ALLOW_RULE (stat); + ALLOW_RULE (stat64); + ALLOW_RULE (statfs); + ALLOW_RULE (statfs64); + ALLOW_RULE (lstat); + ALLOW_RULE (lstat64); + ALLOW_RULE (access); + ALLOW_RULE (getdents); + ALLOW_RULE (getdents64); + ALLOW_RULE (readlink); + ALLOW_RULE (readlinkat); + ALLOW_RULE (utime); + ALLOW_RULE (time); + ALLOW_RULE (fsync); + ALLOW_RULE (umask); + /* 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); + ALLOW_RULE (waitid); + ALLOW_RULE (waitpid); + ALLOW_RULE (wait4); + /* Main loops */ + ALLOW_RULE (poll); + ALLOW_RULE (ppoll); + ALLOW_RULE (fcntl); + ALLOW_RULE (fcntl64); + ALLOW_RULE (eventfd); + ALLOW_RULE (eventfd2); + ALLOW_RULE (pipe); + ALLOW_RULE (pipe2); + /* System */ + ALLOW_RULE (uname); + ALLOW_RULE (sysinfo); + ALLOW_RULE (prctl); + ALLOW_RULE (getrandom); + ALLOW_RULE (clock_gettime); + ALLOW_RULE (clock_getres); + ALLOW_RULE (gettimeofday); + /* Descriptors */ + ALLOW_RULE (close); + ALLOW_RULE (read); + ALLOW_RULE (pread64); + ALLOW_RULE (lseek); + ALLOW_RULE (_llseek); + ALLOW_RULE (fadvise64); + ALLOW_RULE (write); + ALLOW_RULE (writev); + ALLOW_RULE (dup); + ALLOW_RULE (dup2); + ALLOW_RULE (dup3); + /* 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/openat, 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; + + if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, + SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0) + goto out; + if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(openat), 1, + SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0) + goto out; + if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(openat), 1, + SCMP_CMP(2, 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__ */ |