diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0de1d4e3dac90e78969a214e3f304b3ead86f7d..2d5b683677d8192d590327ae2f9bdf11751f7555 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ stages: - code-review - build - test - - seccomp + - sandbox - analysis - docs @@ -227,7 +227,7 @@ build-ubuntu-rolling@x86_64: - .gitlab-ci/checkout-tracker.sh - cd build - ninja clean - - meson configure -Db_coverage=true -Dseccomp=false + - meson configure -Db_coverage=true -Dseccomp=false -Dlandlock=disabled - ninja - | # Remove the many "CI_" variables from the environment. Meson dumps the @@ -313,8 +313,8 @@ test-docs: needs: - build-fedora-container@x86_64 -.seccomp_template: &seccomp - stage: seccomp +.sandbox_template: &sandbox + stage: sandbox script: - .gitlab-ci/checkout-tracker.sh @@ -334,39 +334,39 @@ test-docs: reports: junit: "build/meson-logs/testlog.junit.xml" -seccomp-fedora@x86_64: +sandbox-fedora@x86_64: extends: - .fdo.distribution-image@fedora - .tracker-miners.fedora:36@x86_64 needs: - build-fedora@x86_64 - <<: *seccomp + <<: *sandbox -seccomp-fedora-rawhide@x86_64: +sandbox-fedora-rawhide@x86_64: extends: - .fdo.distribution-image@fedora - .tracker-miners.fedora:rawhide@x86_64 needs: - build-fedora-rawhide@x86_64 allow_failure: true - <<: *seccomp + <<: *sandbox -seccomp-fedora@aarch64: +sandbox-fedora@aarch64: extends: - .fdo.distribution-image@fedora - .tracker-miners.fedora:36@aarch64 needs: - build-fedora@aarch64 allow_failure: true - <<: *seccomp + <<: *sandbox -seccomp-ubuntu@x86_64: +sandbox-ubuntu@x86_64: extends: - .fdo.distribution-image@ubuntu - .tracker-miners.ubuntu:rolling@x86_64 needs: - build-ubuntu-rolling@x86_64 - <<: *seccomp + <<: *sandbox coverage: extends: diff --git a/config-miners.h.meson.in b/config-miners.h.meson.in index 48fa769b00bb88f283ee514d1871abbe19b9bb2a..b6417181eb519835023662c84a915dd77450b283 100644 --- a/config-miners.h.meson.in +++ b/config-miners.h.meson.in @@ -80,6 +80,9 @@ /* Define if btrfs has the necessary ioctl()s */ #mesondefine HAVE_BTRFS_IOCTL +/* Define if landlock is available */ +#mesondefine HAVE_LANDLOCK + /* Define to the address where bug reports for this package should be sent. */ #mesondefine PACKAGE_BUGREPORT diff --git a/meson.build b/meson.build index 415538614c9beb4ff332554cc9833fee1c2cef91..d3d280788894c8d1b5f1f55b2659705eb995699f 100644 --- a/meson.build +++ b/meson.build @@ -181,6 +181,12 @@ else have_btrfs_ioctl = false endif +########################################## +# Check for landlock +########################################## + +have_landlock = cc.has_header('linux/landlock.h', required: get_option('landlock')) + #################################################################### # This section is for tracker-extract dependencies #################################################################### @@ -367,6 +373,7 @@ conf.set('HAVE_POSIX_FADVISE', cc.has_function('posix_fadvise', prefix : '#inclu conf.set('HAVE_STATVFS64', cc.has_header_symbol('sys/statvfs.h', 'statvfs64', args: '-D_LARGEFILE64_SOURCE')) conf.set('HAVE_STRNLEN', cc.has_function('strnlen', prefix : '#include ')) conf.set('HAVE_MEMFD_CREATE', cc.has_function('memfd_create', prefix : '#define _GNU_SOURCE\n#include ')) +conf.set('HAVE_LANDLOCK', have_landlock) conf.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) conf.set_quoted('SHAREDIR', get_option('prefix') / get_option('datadir')) @@ -479,6 +486,7 @@ summary = [ ' Domain prefix: ' + get_option('domain_prefix'), '\nFeature Support:', ' File monitoring: @0@glib'.format(have_fanotify ? 'fanotify ' : ''), + ' Landlock: ' + have_landlock.to_string(), ' BTRFS subvolumes: ' + have_btrfs_ioctl.to_string(), ' Battery/mains power detection: ' + battery_detection_library_name, ' Support for network status detection: ' + have_network_manager.to_string(), @@ -533,6 +541,12 @@ endif message('\n'.join(summary)) -if not get_option('seccomp') - warning('Sandboxing is disabled. Run at your own risk. Distribution is discouraged.') +if not get_option('seccomp') or get_option('landlock').disabled() + if not get_option('seccomp') + warning('Seccomp sandboxing is disabled.') + endif + if get_option('landlock').disabled() + warning('Landlock sandboxing is disabled.') + endif + warning('Run at your own risk. Distribution is discouraged.') endif diff --git a/meson_options.txt b/meson_options.txt index 9bd367f5035ae96c766feb7dd7b32f4f616c916d..c4e251bf884bcbd529eaa40a00ad7f34a30245eb 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -16,7 +16,9 @@ option('miner_rss', type: 'boolean', value: true, option('writeback', type: 'boolean', value: true, description: 'Enable Tracker writeback feature') option('seccomp', type: 'boolean', value: true, - description: 'Enable seccomp support in Tracker metadata extractor') + description: 'Enable seccomp sandboxing support in Tracker metadata extractor') +option('landlock', type: 'feature', value: 'auto', + description: 'Enable landlock sandboxing support in Tracker metadata extractor') option('domain_prefix', type: 'string', value: 'org.freedesktop', description: 'Domain prefix to use, useful for sandboxing') option('miner_fs_cache_location', type: 'string', value: '', diff --git a/src/libtracker-miners-common/meson.build b/src/libtracker-miners-common/meson.build index 22026bbc09bccb6bbe5250af039d44813bb5a780..cc570a7c613f0642c6577b19de77abb7d99bb769 100644 --- a/src/libtracker-miners-common/meson.build +++ b/src/libtracker-miners-common/meson.build @@ -25,6 +25,10 @@ tracker_miners_common_sources = [ enums[0], enums[1], ] +if have_landlock + tracker_miners_common_sources += 'tracker-landlock.c' +endif + tracker_miners_common_dependencies = [glib, gio, gio_unix, libmath, tracker_sparql] if battery_detection_library_name == 'upower' @@ -49,7 +53,13 @@ libtracker_miners_common = static_library('tracker-miners-common', tracker_miners_common_sources, dependencies: tracker_miners_common_dependencies + tracker_miners_common_private_dependencies, c_args: tracker_c_args + [ - '-DTRACKERSHAREDIR="@0@"'.format(tracker_versioned_name), + '-DTRACKERSHAREDIR="@0@"'.format(tracker_versioned_name), + '-DLIBDIR="@0@"'.format(get_option ('libdir')), + '-DDATADIR="@0@"'.format(get_option ('datadir')), + '-DPREFIX="@0@"'.format(get_option ('prefix')), + '-DBUILDROOT="@0@"'.format(meson.build_root()), + '-DSRCROOT="@0@"'.format(meson.source_root()), + '-DLIBEXECDIR="@0@"'.format(join_paths(get_option('prefix'), get_option('libexecdir'))), ], include_directories: [configinc, srcinc], ) diff --git a/src/libtracker-miners-common/tracker-common.h b/src/libtracker-miners-common/tracker-common.h index 7da2b551c943892c9881f762e6dbb9853c769e2e..765f9fb0560613f0bfaddf690e3ccbd388dac68d 100644 --- a/src/libtracker-miners-common/tracker-common.h +++ b/src/libtracker-miners-common/tracker-common.h @@ -40,6 +40,11 @@ #include "tracker-file-utils.h" #include "tracker-fts-config.h" #include "tracker-ioprio.h" + +#ifdef HAVE_LANDLOCK +#include "tracker-landlock.h" +#endif + #include "tracker-miner.h" #include "tracker-miner-proxy.h" #include "tracker-sched.h" diff --git a/src/libtracker-miners-common/tracker-debug.c b/src/libtracker-miners-common/tracker-debug.c index 0db8a369c6fa99e6ddd2eeffa1504d6bb3cf8f79..429eee0a39cc9fb8985ed780280dde627511e161 100644 --- a/src/libtracker-miners-common/tracker-debug.c +++ b/src/libtracker-miners-common/tracker-debug.c @@ -29,6 +29,7 @@ static const GDebugKey tracker_miners_debug_keys[] = { { "monitors", TRACKER_DEBUG_MONITORS }, { "statistics", TRACKER_DEBUG_STATISTICS }, { "status", TRACKER_DEBUG_STATUS }, + { "sandbox", TRACKER_DEBUG_SANDBOX }, }; #endif /* G_ENABLE_DEBUG */ diff --git a/src/libtracker-miners-common/tracker-debug.h b/src/libtracker-miners-common/tracker-debug.h index 3c331dd57b11466228035cceff35f52c5dc7ec9f..605713d7a29d9e8a2ad7bad152e5dce4a5375ce2 100644 --- a/src/libtracker-miners-common/tracker-debug.h +++ b/src/libtracker-miners-common/tracker-debug.h @@ -35,6 +35,7 @@ typedef enum { TRACKER_DEBUG_MONITORS = 1 << 4, TRACKER_DEBUG_STATISTICS = 1 << 5, TRACKER_DEBUG_STATUS = 1 << 6, + TRACKER_DEBUG_SANDBOX = 1 << 7, } TrackerDebugFlag; #ifdef G_ENABLE_DEBUG diff --git a/src/libtracker-miners-common/tracker-landlock.c b/src/libtracker-miners-common/tracker-landlock.c new file mode 100644 index 0000000000000000000000000000000000000000..855dac161ac4cf674964c28fbea9d1d64a1ff1e2 --- /dev/null +++ b/src/libtracker-miners-common/tracker-landlock.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2023, 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. + * + * Author: Carlos Garnacho + */ + +#include "config-miners.h" + +#include "tracker-landlock.h" + +#include +#include +#include +#include +#include + +#include "tracker-debug.h" + +/* Compensate for these syscalls not being wrapped in libc */ +#define CREATE_RULESET(attr, flags) \ + syscall (SYS_landlock_create_ruleset, (attr), \ + (attr) != NULL ? sizeof *(attr) : 0, \ + flags) + +#define ADD_RULE(fd, type, attr, flags) \ + syscall (SYS_landlock_add_rule, fd, type, (attr), flags) + +#define RESTRICT_SELF(fd, flags) \ + syscall (SYS_landlock_restrict_self, fd, flags) + +/* Cautious defines of flags in newer ABI versions */ +#ifndef LANDLOCK_ACCESS_FS_REFER +#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13) +#endif + +#ifndef LANDLOCK_ACCESS_FS_TRUNCATE +#define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) +#endif + +typedef struct _TrackerLandlockRule TrackerLandlockRule; + +struct _TrackerLandlockRule +{ + const gchar *path; + guint64 flags; +}; + +gboolean +get_supported_fs_flags (guint32 *flags_out) +{ + guint64 supported_abi_flags[] = { + /* Version 1 */ + (LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_WRITE_FILE | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR | + LANDLOCK_ACCESS_FS_REMOVE_DIR | + LANDLOCK_ACCESS_FS_REMOVE_FILE | + LANDLOCK_ACCESS_FS_MAKE_CHAR | + LANDLOCK_ACCESS_FS_MAKE_DIR | + LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_MAKE_SOCK | + LANDLOCK_ACCESS_FS_MAKE_FIFO | + LANDLOCK_ACCESS_FS_MAKE_BLOCK | + LANDLOCK_ACCESS_FS_MAKE_SYM), + /* Version 2 */ + LANDLOCK_ACCESS_FS_REFER, + /* Version 3 */ + LANDLOCK_ACCESS_FS_TRUNCATE, + }; + guint32 flags = 0; + int i, abi; + + abi = CREATE_RULESET (NULL, LANDLOCK_CREATE_RULESET_VERSION); + if (abi < 0) { + g_critical ("Could not get landlock supported ABI: %m"); + return FALSE; + } + + for (i = 0; i < MIN (G_N_ELEMENTS (supported_abi_flags), abi); i++) + flags |= supported_abi_flags[i]; + + *flags_out = flags; + + return TRUE; +} + +static void +add_rule (int landlock_fd, + const gchar *path, + guint64 flags) +{ + struct landlock_path_beneath_attr attr = { 0, }; + int fd; + int result; + + TRACKER_NOTE (SANDBOX, g_message ("Adding Landlock rule for '%s', flags %" G_GINT64_MODIFIER "x", path, flags)); + + if (!g_file_test (path, G_FILE_TEST_EXISTS)) { + g_debug ("Path %s does not exist in filesystem", path); + return; + } + + fd = open (path, O_PATH | O_CLOEXEC); + if (fd < 0) { + g_warning ("Could not open '%s' to apply landlock rules: %m", path); + return; + } + + attr = (struct landlock_path_beneath_attr) { + .allowed_access = flags, + .parent_fd = fd, + }; + + result = ADD_RULE (landlock_fd, LANDLOCK_RULE_PATH_BENEATH, &attr, 0); + close(fd); + if (result != 0) { + g_warning ("Could not add landlock rule for '%s': %m", path); + return; + } +} + +static gboolean +create_ruleset (int *landlock_fd) +{ + struct landlock_ruleset_attr attr; + int fd; + guint32 flags; + + /* Get supported flags per the landlock ABI available */ + if (!get_supported_fs_flags (&flags)) + return FALSE; + + /* Create ruleset */ + attr = (struct landlock_ruleset_attr) { + .handled_access_fs = flags, + }; + + fd = CREATE_RULESET (&attr, 0); + if (landlock_fd < 0) { + g_critical ("Failed to create landlock ruleset: %m"); + return FALSE; + } + + *landlock_fd = fd; + + return TRUE; +} + +static gboolean +apply_ruleset (int landlock_fd) +{ + /* Restrict any future new permission, necessary for the next step */ + if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { + g_critical ("Failed to restrict new privileges: %m"); + return FALSE; + } + + if (RESTRICT_SELF (landlock_fd, 0) != 0) { + g_critical ("Failed to apply landlock ruleset: %m"); + return FALSE; + } + + return TRUE; +} + +gboolean +tracker_landlock_init (const gchar * const *indexed_folders) +{ + TrackerLandlockRule stock_rules[] = { + /* Allow access to the executable itself */ + { LIBEXECDIR "/tracker-extract-3", + LANDLOCK_ACCESS_FS_EXECUTE }, + /* Library dirs, as we shockingly use libraries. Extends to /usr */ + { PREFIX "/" LIBDIR, + (LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, +#if INTPTR_MAX == INT64_MAX + { "/usr/lib64", + (LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, +#endif + { "/usr/lib", + (LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, + /* Data dir, to access miscellaneous files. Extends to /usr */ + { PREFIX "/" DATADIR, + (LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, + { "/usr/share", + (LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, + /* Necessary for libosinfo in Ubuntu/Debian */ + { "/var/lib/usbutils", + LANDLOCK_ACCESS_FS_READ_FILE }, + /* Necessary for mount monitors */ + { "/proc/mounts", + LANDLOCK_ACCESS_FS_READ_FILE }, + { "/proc/self/mountinfo", + LANDLOCK_ACCESS_FS_READ_FILE }, + /* Necessary for g_get_user_name() */ + { "/etc/passwd", + LANDLOCK_ACCESS_FS_READ_FILE }, + }; + TrackerLandlockRule homedir_rules[] = { + /* Disable file access to sensitive folders the extractor has + * no business with. Since a flag bit needs to be set, only + * allow dir read access. + */ + { ".ssh", LANDLOCK_ACCESS_FS_READ_DIR }, + { ".pki", LANDLOCK_ACCESS_FS_READ_DIR }, + { ".gnupg", LANDLOCK_ACCESS_FS_READ_DIR }, + }; + g_autofree gchar *current_dir = NULL, *cache_dir = NULL; + g_auto (GStrv) library_paths = NULL; + const gchar *ld_library_path = NULL; + int i, landlock_fd; + gboolean retval; + + if (!create_ruleset (&landlock_fd)) + return FALSE; + + /* Populate ruleset */ + for (i = 0; i < G_N_ELEMENTS (stock_rules); i++) { + add_rule (landlock_fd, stock_rules[i].path, + stock_rules[i].flags); + } + + for (i = 0; i < G_N_ELEMENTS (homedir_rules); i++) { + g_autofree gchar *homedir_path = NULL; + + homedir_path = g_build_filename (g_get_home_dir (), + homedir_rules[i].path, NULL); + add_rule (landlock_fd, homedir_path, homedir_rules[i].flags); + } + + for (i = 0; indexed_folders && indexed_folders[i]; i++) { + add_rule (landlock_fd, + indexed_folders[i], + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR); + } + + /* Cater for development environments */ + ld_library_path = g_getenv ("LD_LIBRARY_PATH"); + if (ld_library_path) { + library_paths = g_strsplit (ld_library_path, ":", -1); + for (i = 0; library_paths && library_paths[i]; i++) { + add_rule (landlock_fd, + library_paths[i], + LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR); + } + } + + current_dir = g_get_current_dir (); + + /* Detect running in-tree */ + if (g_strcmp0 (current_dir, BUILDROOT) == 0) { + TrackerLandlockRule in_tree_rules[] = { + { BUILDROOT, + (LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR | + LANDLOCK_ACCESS_FS_EXECUTE) }, + { SRCROOT, + (LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_DIR) }, + }; + + for (i = 0; i < G_N_ELEMENTS (in_tree_rules); i++) { + add_rule (landlock_fd, in_tree_rules[i].path, + in_tree_rules[i].flags); + } + } + + /* Add user cache for readonly databases */ +#ifdef MINER_FS_CACHE_LOCATION + add_rule (landlock_fd, MINER_FS_CACHE_LOCATION, + LANDLOCK_ACCESS_FS_READ_FILE); +#else + cache_dir = g_build_filename (g_get_user_cache_dir (), "tracker3", "files", NULL); + add_rule (landlock_fd, cache_dir, + LANDLOCK_ACCESS_FS_READ_FILE); +#endif + + TRACKER_NOTE (SANDBOX, g_message ("Applying Landlock ruleset to PID %d", getpid ())); + retval = apply_ruleset (landlock_fd); + close (landlock_fd); + + return retval; +} diff --git a/src/libtracker-miners-common/tracker-landlock.h b/src/libtracker-miners-common/tracker-landlock.h new file mode 100644 index 0000000000000000000000000000000000000000..dbb4f8b00f11ad7bea4e780d6b3f5344ffad4d77 --- /dev/null +++ b/src/libtracker-miners-common/tracker-landlock.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023, 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. + * + * Author: Carlos Garnacho + */ + +#ifndef __TRACKER_LANDLOCK_H__ +#define __TRACKER_LANDLOCK_H__ + +#include + +gboolean tracker_landlock_init (const gchar * const *allowed_paths); + +#endif /* __TRACKER_LANDLOCK_H__ */ diff --git a/src/miners/fs/tracker-extract-watchdog.c b/src/miners/fs/tracker-extract-watchdog.c index da7d74ef6475ff53e428dc96db5ab14cf98e0893..ccf89c946a2beef721d1d254abc234ae22f335b6 100644 --- a/src/miners/fs/tracker-extract-watchdog.c +++ b/src/miners/fs/tracker-extract-watchdog.c @@ -40,6 +40,7 @@ static guint signals[N_SIGNALS] = { 0, }; enum { PROP_0, PROP_SPARQL_CONN, + PROP_INDEXING_TREE, N_PROPS, }; @@ -54,6 +55,7 @@ struct _TrackerExtractWatchdog { GDBusConnection *conn; TrackerEndpoint *endpoint; TrackerFilesInterface *files_interface; + TrackerIndexingTree *indexing_tree; guint progress_signal_id; guint error_signal_id; int persistence_fd; @@ -161,6 +163,9 @@ tracker_extract_watchdog_finalize (GObject *object) if (watchdog->persistence_fd) close (watchdog->persistence_fd); + g_clear_object (&watchdog->sparql_conn); + g_clear_object (&watchdog->indexing_tree); + G_OBJECT_CLASS (tracker_extract_watchdog_parent_class)->finalize (object); } @@ -176,6 +181,9 @@ tracker_extract_watchdog_set_property (GObject *object, case PROP_SPARQL_CONN: watchdog->sparql_conn = g_value_dup_object (value); break; + case PROP_INDEXING_TREE: + watchdog->indexing_tree = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -211,6 +219,12 @@ tracker_extract_watchdog_class_init (TrackerExtractWatchdogClass *klass) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + props[PROP_INDEXING_TREE] = + g_param_spec_object ("indexing-tree", NULL, NULL, + TRACKER_TYPE_INDEXING_TREE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, props); } @@ -223,10 +237,12 @@ tracker_extract_watchdog_init (TrackerExtractWatchdog *watchdog) } TrackerExtractWatchdog * -tracker_extract_watchdog_new (TrackerSparqlConnection *sparql_conn) +tracker_extract_watchdog_new (TrackerSparqlConnection *sparql_conn, + TrackerIndexingTree *indexing_tree) { return g_object_new (TRACKER_TYPE_EXTRACT_WATCHDOG, "sparql-conn", sparql_conn, + "indexing-tree", indexing_tree, NULL); } @@ -317,6 +333,38 @@ wait_check_async_cb (GObject *object, g_signal_emit (watchdog, signals[STATUS], 0, "Idle", 1.0, 0); } +static GStrv +get_indexed_folders (TrackerExtractWatchdog *watchdog) +{ + GArray *array; + GList *roots, *l; + + array = g_array_new (TRUE, FALSE, sizeof (gchar*)); + roots = tracker_indexing_tree_list_roots (watchdog->indexing_tree); + + for (l = roots; l; l = l->next) { + GFile *file = l->data; + gchar *path = NULL; + + path = g_file_get_path (file); + if (path) + g_array_append_val (array, path); + } + + return (GStrv) g_array_free (array, FALSE); +} + +static void +extractor_child_setup (gpointer user_data) +{ +#ifdef HAVE_LANDLOCK + const gchar * const *indexed_folders = user_data; + + if (!tracker_landlock_init (indexed_folders)) + g_assert_not_reached (); +#endif +} + static gboolean setup_context (TrackerExtractWatchdog *watchdog, GError **error) @@ -341,6 +389,11 @@ setup_context (TrackerExtractWatchdog *watchdog, watchdog->launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); g_subprocess_launcher_take_fd (watchdog->launcher, fd_pair[1], REMOTE_FD_NUMBER); + g_subprocess_launcher_set_child_setup (watchdog->launcher, + extractor_child_setup, + get_indexed_folders (watchdog), + (GDestroyNotify) g_strfreev); + socket = g_socket_new_from_fd (fd_pair[0], error); if (!socket) { close (fd_pair[0]); diff --git a/src/miners/fs/tracker-extract-watchdog.h b/src/miners/fs/tracker-extract-watchdog.h index 64e8e125ed533baeddb3e260ae8630a3e2d39a36..0efbb41ade1ba20b05cd7a8b4a0bd058a64ff711 100644 --- a/src/miners/fs/tracker-extract-watchdog.h +++ b/src/miners/fs/tracker-extract-watchdog.h @@ -22,6 +22,8 @@ #include +#include "tracker-indexing-tree.h" + G_BEGIN_DECLS #define TRACKER_TYPE_EXTRACT_WATCHDOG (tracker_extract_watchdog_get_type ()) @@ -31,7 +33,8 @@ G_DECLARE_FINAL_TYPE (TrackerExtractWatchdog, TRACKER, EXTRACT_WATCHDOG, GObject) -TrackerExtractWatchdog * tracker_extract_watchdog_new (TrackerSparqlConnection *sparql_conn); +TrackerExtractWatchdog * tracker_extract_watchdog_new (TrackerSparqlConnection *sparql_conn, + TrackerIndexingTree *indexing_tree); void tracker_extract_watchdog_ensure_started (TrackerExtractWatchdog *watchdog); diff --git a/src/miners/fs/tracker-miner-files.c b/src/miners/fs/tracker-miner-files.c index e254d281eb5b9605fc3b8ece1c3fa0c8a458db02..a25295d7e2de497220d33ae76377b6e53948bf01 100644 --- a/src/miners/fs/tracker-miner-files.c +++ b/src/miners/fs/tracker-miner-files.c @@ -1072,7 +1072,8 @@ miner_files_constructed (GObject *object) domain_name = tracker_domain_ontology_get_domain (mf->private->domain_ontology, NULL); mf->private->extract_watchdog = - tracker_extract_watchdog_new (tracker_miner_get_connection (TRACKER_MINER (mf))); + tracker_extract_watchdog_new (tracker_miner_get_connection (TRACKER_MINER (mf)), + tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (mf))); g_signal_connect (mf->private->extract_watchdog, "lost", G_CALLBACK (on_extractor_lost), mf); g_signal_connect (mf->private->extract_watchdog, "status", diff --git a/src/tracker/tracker-extract.c b/src/tracker/tracker-extract.c index 3647557896e482a2ce2f864161ac2479b00a2edd..8d5913290793d0a28c3d84fc45cc9bffd436023f 100644 --- a/src/tracker/tracker-extract.c +++ b/src/tracker/tracker-extract.c @@ -47,6 +47,18 @@ static GOptionEntry entries[] = { { NULL } }; +static void +extractor_child_setup (gpointer user_data) +{ +#ifdef HAVE_LANDLOCK + g_autofree gchar *folder = NULL; + + folder = g_path_get_dirname (user_data); + + if (!tracker_landlock_init ((const gchar*[]) { folder, NULL })) + g_assert_not_reached (); +#endif +} static gint extract_files (char *output_format) @@ -69,7 +81,9 @@ extract_files (char *output_format) "--output-format", output_format, "--file", *p, NULL }; - g_spawn_sync(NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL, NULL, &error); + g_spawn_sync (NULL, argv, NULL, G_SPAWN_DEFAULT, + extractor_child_setup, *p, + NULL, NULL, NULL, &error); if (error) { g_printerr ("%s: %s\n",