diff --git a/SOURCES/backport-seccomp-improvements.diff b/SOURCES/backport-seccomp-improvements.diff new file mode 100644 index 0000000..ed827fa --- /dev/null +++ b/SOURCES/backport-seccomp-improvements.diff @@ -0,0 +1,3633 @@ +From ec32dc4f0c7bb8f8583b3d5fb844a52d3221f969 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sat, 23 Sep 2023 10:42:37 +0200 +Subject: [PATCH 01/22] tracker-extract: Drop SIGINT/SIGTERM handlers + +These bring some questions if using seccomp for the full +process (e.g. requiring additional syscalls, or glib spawning +a thread for it), and are not really mandatory since there's +no requirements for a clean exit. + +The only thing that is somewhat lost is ease at valgrinding +with noise from things "definitely lost" in the abrupt termination, +but that does already require manually disabling the seccomp +jail, it's not a big stretch to pile up more local hacks, or +ignore the noise. +--- + src/tracker-extract/tracker-main.c | 65 ------------------------------ + 1 file changed, 65 deletions(-) + +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 1d3e32567..7732f443d 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -138,66 +138,6 @@ initialize_priority_and_scheduling (TrackerSchedIdle sched_idle, + } + } + +-static void +-initialize_directories (void) +-{ +- gchar *user_data_dir; +- +- /* NOTE: We don't create the database directories here, the +- * tracker-db-manager does that for us. +- */ +- +- user_data_dir = g_build_filename (g_get_user_data_dir (), +- "tracker", +- NULL); +- +- /* g_message ("Checking directory exists:'%s'", user_data_dir); */ +- g_mkdir_with_parents (user_data_dir, 00755); +- +- g_free (user_data_dir); +-} +- +-static gboolean +-signal_handler (gpointer user_data) +-{ +- int signo = GPOINTER_TO_INT (user_data); +- +- static gboolean in_loop = FALSE; +- +- /* Die if we get re-entrant signals handler calls */ +- if (in_loop) { +- _exit (EXIT_FAILURE); +- } +- +- switch (signo) { +- case SIGTERM: +- case SIGINT: +- in_loop = TRUE; +- g_main_loop_quit (main_loop); +- +- /* Fall through */ +- default: +- if (g_strsignal (signo)) { +- g_print ("\n"); +- g_print ("Received signal:%d->'%s'\n", +- signo, +- g_strsignal (signo)); +- } +- break; +- } +- +- return G_SOURCE_CONTINUE; +-} +- +-static void +-initialize_signal_handler (void) +-{ +-#ifndef G_OS_WIN32 +- g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); +- g_unix_signal_add (SIGINT, signal_handler, GINT_TO_POINTER (SIGINT)); +-#endif /* G_OS_WIN32 */ +-} +- + static void + log_handler (const gchar *domain, + GLogLevelFlags log_level, +@@ -433,9 +373,6 @@ main (int argc, char *argv[]) + return run_standalone (config); + } + +- /* Initialize subsystems */ +- initialize_directories (); +- + /* This makes sure we don't steal all the system's resources */ + initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), TRUE); + +@@ -509,8 +446,6 @@ main (int argc, char *argv[]) + G_CALLBACK (on_decorator_items_available), + main_loop); + +- initialize_signal_handler (); +- + g_main_loop_run (main_loop); + + my_main_loop = main_loop; +-- +2.43.0 + + +From 8e826fd2952c40b4fc991aaef86d614bb3dd5a99 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 24 Sep 2023 15:53:22 +0200 +Subject: [PATCH 02/22] tracker-extract: Drop handling of wait-for-miner-fs + +Even though this setting is off by default, that is the stock +behavior of tracker-miner-fs, by activating the tracker-extract-3 +D-Bus name after going idle. + +Furthermore, enabling this setting will have clunky interaction +with the current behavior since 3.1.0 that tracker-miner-fs-3 +forwards the tracker-extract-3 status (commit bd3ce694d7), since +tracker-extract-3 activity will make the tracker-miner-fs-3 status +"non-idle", which will pause the extractor, which will make the miner +idle, which will unpause the extractor, ... + +It's arguable that we should keep supporting this as a setting +altogether, so just drop the tracker-extract-3 side code handling +this setting. +--- + .../tracker-extract-controller.c | 168 ------------------ + 1 file changed, 168 deletions(-) + +diff --git a/src/tracker-extract/tracker-extract-controller.c b/src/tracker-extract/tracker-extract-controller.c +index 9c03112bb..3a34a8dbf 100644 +--- a/src/tracker-extract/tracker-extract-controller.c ++++ b/src/tracker-extract/tracker-extract-controller.c +@@ -30,185 +30,19 @@ enum { + + struct TrackerExtractControllerPrivate { + TrackerDecorator *decorator; +- TrackerConfig *config; + GCancellable *cancellable; + GDBusConnection *connection; +- guint watch_id; +- guint progress_signal_id; + gint paused; + }; + + G_DEFINE_TYPE (TrackerExtractController, tracker_extract_controller, G_TYPE_OBJECT) + +-static void +-files_miner_idleness_changed (TrackerExtractController *self, +- gboolean idle) +-{ +- if (idle && self->priv->paused) { +- tracker_miner_resume (TRACKER_MINER (self->priv->decorator)); +- self->priv->paused = FALSE; +- } else if (!idle && !self->priv->paused) { +- self->priv->paused = FALSE; +- tracker_miner_pause (TRACKER_MINER (self->priv->decorator)); +- } +-} +- +-static void +-files_miner_status_changed (TrackerExtractController *self, +- const gchar *status) +-{ +- files_miner_idleness_changed (self, g_str_equal (status, "Idle")); +-} +- +-static void +-files_miner_get_status_cb (GObject *source, +- GAsyncResult *result, +- gpointer user_data) +-{ +- TrackerExtractController *self = user_data; +- GDBusConnection *conn = (GDBusConnection *) source; +- GVariant *reply; +- const gchar *status; +- GError *error = NULL; +- +- reply = g_dbus_connection_call_finish (conn, result, &error); +- if (!reply) { +- g_debug ("Failed to get tracker-miner-fs status: %s", +- error->message); +- g_clear_error (&error); +- } else { +- g_variant_get (reply, "(&s)", &status); +- files_miner_status_changed (self, status); +- g_variant_unref (reply); +- } +- +- g_clear_object (&self->priv->cancellable); +- g_object_unref (self); +-} +- +-static void +-appeared_cb (GDBusConnection *connection, +- const gchar *name, +- const gchar *name_owner, +- gpointer user_data) +-{ +- TrackerExtractController *self = user_data; +- +- /* Get initial status */ +- self->priv->cancellable = g_cancellable_new (); +- g_dbus_connection_call (connection, +- "org.freedesktop.Tracker1.Miner.Files", +- "/org/freedesktop/Tracker1/Miner/Files", +- "org.freedesktop.Tracker1.Miner", +- "GetStatus", +- NULL, +- G_VARIANT_TYPE ("(s)"), +- G_DBUS_CALL_FLAGS_NO_AUTO_START, +- -1, +- self->priv->cancellable, +- files_miner_get_status_cb, +- g_object_ref (self)); +-} +- +-static void +-vanished_cb (GDBusConnection *connection, +- const gchar *name, +- gpointer user_data) +-{ +- TrackerExtractController *self = user_data; +- +- /* tracker-miner-fs vanished, we don't have anything to wait for +- * anymore. */ +- files_miner_idleness_changed (self, TRUE); +-} +- +-static void +-files_miner_progress_cb (GDBusConnection *connection, +- const gchar *sender_name, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *signal_name, +- GVariant *parameters, +- gpointer user_data) +-{ +- TrackerExtractController *self = user_data; +- const gchar *status; +- +- g_return_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sdi)"))); +- +- /* If we didn't get the initial status yet, ignore Progress signals */ +- if (self->priv->cancellable) +- return; +- +- g_variant_get (parameters, "(&sdi)", &status, NULL, NULL); +- files_miner_status_changed (self, status); +-} +- +-static void +-disconnect_all (TrackerExtractController *self) +-{ +- GDBusConnection *conn = self->priv->connection; +- +- if (self->priv->watch_id != 0) +- g_bus_unwatch_name (self->priv->watch_id); +- self->priv->watch_id = 0; +- +- if (self->priv->progress_signal_id != 0) +- g_dbus_connection_signal_unsubscribe (conn, +- self->priv->progress_signal_id); +- self->priv->progress_signal_id = 0; +- +- if (self->priv->cancellable) +- g_cancellable_cancel (self->priv->cancellable); +- g_clear_object (&self->priv->cancellable); +-} +- +-static void +-update_wait_for_miner_fs (TrackerExtractController *self) +-{ +- GDBusConnection *conn = self->priv->connection; +- +- if (tracker_config_get_wait_for_miner_fs (self->priv->config)) { +- self->priv->progress_signal_id = +- g_dbus_connection_signal_subscribe (conn, +- "org.freedesktop.Tracker1.Miner.Files", +- "org.freedesktop.Tracker1.Miner", +- "Progress", +- "/org/freedesktop/Tracker1/Miner/Files", +- NULL, +- G_DBUS_SIGNAL_FLAGS_NONE, +- files_miner_progress_cb, +- self, NULL); +- +- /* appeared_cb is guaranteed to be called even if the service +- * was already running, so we'll start the miner from there. */ +- self->priv->watch_id = g_bus_watch_name_on_connection (conn, +- "org.freedesktop.Tracker1.Miner.Files", +- G_BUS_NAME_WATCHER_FLAGS_NONE, +- appeared_cb, +- vanished_cb, +- self, NULL); +- } else { +- disconnect_all (self); +- files_miner_idleness_changed (self, TRUE); +- } +-} +- + static void + tracker_extract_controller_constructed (GObject *object) + { + TrackerExtractController *self = (TrackerExtractController *) object; + + G_OBJECT_CLASS (tracker_extract_controller_parent_class)->constructed (object); +- +- g_assert (self->priv->decorator != NULL); +- +- self->priv->config = g_object_ref (tracker_main_get_config ()); +- g_signal_connect_object (self->priv->config, +- "notify::wait-for-miner-fs", +- G_CALLBACK (update_wait_for_miner_fs), +- self, G_CONNECT_SWAPPED); +- update_wait_for_miner_fs (self); + } + + static void +@@ -253,9 +87,7 @@ tracker_extract_controller_dispose (GObject *object) + { + TrackerExtractController *self = (TrackerExtractController *) object; + +- disconnect_all (self); + g_clear_object (&self->priv->decorator); +- g_clear_object (&self->priv->config); + + G_OBJECT_CLASS (tracker_extract_controller_parent_class)->dispose (object); + } +-- +2.43.0 + + +From 874665ba0edecd826fd2cedd989edfc3102f5fa5 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 24 Sep 2023 14:20:01 +0200 +Subject: [PATCH 03/22] tracker-extract: Handle configuration through D-Bus + +Add an interface on tracker-miner-fs-3 so that tracker-extract-3 +can get the relevant settings without using DConf/GSettings directly. +This replaces all settings usage from tracker-extract-3. +--- + src/libtracker-extract/tracker-extract-info.c | 12 +- + src/libtracker-extract/tracker-extract-info.h | 5 +- + src/miners/fs/Makefile.am | 2 + + src/miners/fs/meson.build | 1 + + src/miners/fs/tracker-files-interface.c | 184 ++++++++++ + src/miners/fs/tracker-files-interface.h | 35 ++ + src/miners/fs/tracker-main.c | 6 + + src/tracker-extract/Makefile.am | 2 - + src/tracker-extract/meson.build | 1 - + src/tracker-extract/tracker-config.c | 328 ------------------ + src/tracker-extract/tracker-config.h | 61 ---- + .../tracker-extract-controller.c | 61 ++++ + src/tracker-extract/tracker-extract-epub.c | 21 +- + src/tracker-extract/tracker-extract-html.c | 4 +- + .../tracker-extract-msoffice-xml.c | 6 +- + .../tracker-extract-msoffice.c | 4 +- + src/tracker-extract/tracker-extract-oasis.c | 6 +- + src/tracker-extract/tracker-extract-pdf.c | 4 +- + src/tracker-extract/tracker-extract-text.c | 5 +- + src/tracker-extract/tracker-extract.c | 19 +- + src/tracker-extract/tracker-extract.h | 3 + + src/tracker-extract/tracker-main.c | 45 +-- + src/tracker-extract/tracker-main.h | 5 - + .../tracker-extract-info-test.c | 4 +- + 24 files changed, 348 insertions(+), 476 deletions(-) + create mode 100644 src/miners/fs/tracker-files-interface.c + create mode 100644 src/miners/fs/tracker-files-interface.h + delete mode 100644 src/tracker-extract/tracker-config.c + delete mode 100644 src/tracker-extract/tracker-config.h + +diff --git a/src/libtracker-extract/tracker-extract-info.c b/src/libtracker-extract/tracker-extract-info.c +index 8e445ecad..b69630b83 100644 +--- a/src/libtracker-extract/tracker-extract-info.c ++++ b/src/libtracker-extract/tracker-extract-info.c +@@ -44,6 +44,8 @@ struct _TrackerExtractInfo + GFile *file; + gchar *mimetype; + ++ gint max_text; ++ + gint ref_count; + }; + +@@ -64,7 +66,8 @@ G_DEFINE_BOXED_TYPE (TrackerExtractInfo, tracker_extract_info, + **/ + TrackerExtractInfo * + tracker_extract_info_new (GFile *file, +- const gchar *mimetype) ++ const gchar *mimetype, ++ gint max_text) + { + TrackerExtractInfo *info; + +@@ -73,6 +76,7 @@ tracker_extract_info_new (GFile *file, + info = g_slice_new0 (TrackerExtractInfo); + info->file = g_object_ref (file); + info->mimetype = g_strdup (mimetype); ++ info->max_text = max_text; + + info->resource = NULL; + +@@ -220,3 +224,9 @@ tracker_extract_info_set_resource (TrackerExtractInfo *info, + g_object_ref (resource); + info->resource = resource; + } ++ ++gint ++tracker_extract_info_get_max_text (TrackerExtractInfo *info) ++{ ++ return info->max_text; ++} +diff --git a/src/libtracker-extract/tracker-extract-info.h b/src/libtracker-extract/tracker-extract-info.h +index 537efb3b4..fd3c27d95 100644 +--- a/src/libtracker-extract/tracker-extract-info.h ++++ b/src/libtracker-extract/tracker-extract-info.h +@@ -36,12 +36,15 @@ typedef struct _TrackerExtractInfo TrackerExtractInfo; + GType tracker_extract_info_get_type (void) G_GNUC_CONST; + + TrackerExtractInfo * tracker_extract_info_new (GFile *file, +- const gchar *mimetype); ++ const gchar *mimetype, ++ gint max_text); + TrackerExtractInfo * tracker_extract_info_ref (TrackerExtractInfo *info); + void tracker_extract_info_unref (TrackerExtractInfo *info); + GFile * tracker_extract_info_get_file (TrackerExtractInfo *info); + const gchar * tracker_extract_info_get_mimetype (TrackerExtractInfo *info); + ++gint tracker_extract_info_get_max_text (TrackerExtractInfo *info); ++ + TrackerResource * tracker_extract_info_get_resource (TrackerExtractInfo *info); + void tracker_extract_info_set_resource (TrackerExtractInfo *info, + TrackerResource *resource); +diff --git a/src/miners/fs/Makefile.am b/src/miners/fs/Makefile.am +index c8af61099..cb812e0b5 100644 +--- a/src/miners/fs/Makefile.am ++++ b/src/miners/fs/Makefile.am +@@ -33,6 +33,8 @@ tracker_miner_fs_SOURCES = \ + tracker-config.h \ + tracker-extract-watchdog.c \ + tracker-extract-watchdog.h \ ++ tracker-files-interface.c \ ++ tracker-files-interface.h \ + tracker-main.c \ + tracker-miner-files.c \ + tracker-miner-files.h \ +diff --git a/src/miners/fs/meson.build b/src/miners/fs/meson.build +index 288610b97..c26c0240e 100644 +--- a/src/miners/fs/meson.build ++++ b/src/miners/fs/meson.build +@@ -1,6 +1,7 @@ + sources = [ + 'tracker-config.c', + 'tracker-extract-watchdog.c', ++ 'tracker-files-interface.c', + 'tracker-main.c', + 'tracker-miner-files.c', + 'tracker-miner-files-index.c', +diff --git a/src/miners/fs/tracker-files-interface.c b/src/miners/fs/tracker-files-interface.c +new file mode 100644 +index 000000000..0e259a6ce +--- /dev/null ++++ b/src/miners/fs/tracker-files-interface.c +@@ -0,0 +1,184 @@ ++/* ++ * 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 General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 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 ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU 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.h" ++ ++#include "tracker-files-interface.h" ++ ++struct _TrackerFilesInterface ++{ ++ GObject parent_instance; ++ GDBusConnection *connection; ++ GSettings *settings; ++ guint object_id; ++}; ++ ++enum { ++ PROP_0, ++ PROP_CONNECTION, ++ N_PROPS, ++}; ++ ++static GParamSpec *props[N_PROPS] = { 0, }; ++ ++static const gchar *introspection_xml = ++ "" ++ " " ++ " " ++ " " ++ ""; ++ ++G_DEFINE_TYPE (TrackerFilesInterface, tracker_files_interface, G_TYPE_OBJECT) ++ ++static void ++tracker_files_interface_init (TrackerFilesInterface *files_interface) ++{ ++} ++ ++static GVariant * ++handle_get_property (GDBusConnection *connection, ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *property_name, ++ GError **error, ++ gpointer user_data) ++{ ++ TrackerFilesInterface *files_interface = user_data; ++ ++ if (g_strcmp0 (object_path, "/org/freedesktop/Tracker3/Files") != 0 || ++ g_strcmp0 (interface_name, "org.freedesktop.Tracker3.Files") != 0) { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, ++ "Wrong object/interface"); ++ return NULL; ++ } ++ ++ if (g_strcmp0 (property_name, "ExtractorConfig") == 0) { ++ GVariantBuilder builder; ++ ++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); ++ g_variant_builder_add (&builder, "{sv}", "max-bytes", ++ g_settings_get_value (files_interface->settings, "max-bytes")); ++ ++ return g_variant_builder_end (&builder); ++ } else { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, ++ "Unknown property"); ++ return NULL; ++ } ++} ++ ++static void ++tracker_files_interface_constructed (GObject *object) ++{ ++ TrackerFilesInterface *files_interface = TRACKER_FILES_INTERFACE (object); ++ GDBusInterfaceVTable vtable = { NULL, handle_get_property, NULL }; ++ g_autoptr (GDBusNodeInfo) introspection_data = NULL; ++ ++ G_OBJECT_CLASS (tracker_files_interface_parent_class)->constructed (object); ++ ++ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); ++ files_interface->object_id = ++ g_dbus_connection_register_object (files_interface->connection, ++ "/org/freedesktop/Tracker3/Files", ++ introspection_data->interfaces[0], ++ &vtable, object, NULL, NULL); ++ ++ files_interface->settings = g_settings_new ("org.freedesktop.Tracker.Extract"); ++} ++ ++static void ++tracker_files_interface_finalize (GObject *object) ++{ ++ TrackerFilesInterface *files_interface = TRACKER_FILES_INTERFACE (object); ++ ++ g_dbus_connection_unregister_object (files_interface->connection, ++ files_interface->object_id); ++ g_clear_object (&files_interface->connection); ++ g_clear_object (&files_interface->settings); ++ ++ G_OBJECT_CLASS (tracker_files_interface_parent_class)->finalize (object); ++} ++ ++static void ++tracker_files_interface_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ TrackerFilesInterface *files_interface = TRACKER_FILES_INTERFACE (object); ++ ++ switch (prop_id) { ++ case PROP_CONNECTION: ++ files_interface->connection = g_value_dup_object (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++tracker_files_interface_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ TrackerFilesInterface *files_interface = TRACKER_FILES_INTERFACE (object); ++ ++ switch (prop_id) { ++ case PROP_CONNECTION: ++ g_value_set_object (value, files_interface->connection); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++tracker_files_interface_class_init (TrackerFilesInterfaceClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->constructed = tracker_files_interface_constructed; ++ object_class->finalize = tracker_files_interface_finalize; ++ object_class->set_property = tracker_files_interface_set_property; ++ object_class->get_property = tracker_files_interface_get_property; ++ ++ props[PROP_CONNECTION] = ++ g_param_spec_object ("connection", ++ NULL, NULL, ++ G_TYPE_DBUS_CONNECTION, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ ++ g_object_class_install_properties (object_class, N_PROPS, props); ++} ++ ++TrackerFilesInterface * ++tracker_files_interface_new (GDBusConnection *connection) ++{ ++ return g_object_new (TRACKER_TYPE_FILES_INTERFACE, ++ "connection", connection, ++ NULL); ++} +diff --git a/src/miners/fs/tracker-files-interface.h b/src/miners/fs/tracker-files-interface.h +new file mode 100644 +index 000000000..e040e41d0 +--- /dev/null ++++ b/src/miners/fs/tracker-files-interface.h +@@ -0,0 +1,35 @@ ++/* ++ * 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 General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 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 ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU 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_FILES_INTERFACE_H__ ++#define __TRACKER_FILES_INTERFACE_H__ ++ ++#include ++ ++#define TRACKER_TYPE_FILES_INTERFACE (tracker_files_interface_get_type ()) ++G_DECLARE_FINAL_TYPE (TrackerFilesInterface, ++ tracker_files_interface, ++ TRACKER, FILES_INTERFACE, ++ GObject) ++ ++TrackerFilesInterface * tracker_files_interface_new (GDBusConnection *connection); ++ ++#endif /* __TRACKER_FILES_INTERFACE_H__ */ +diff --git a/src/miners/fs/tracker-main.c b/src/miners/fs/tracker-main.c +index 09a838942..e7e809560 100644 +--- a/src/miners/fs/tracker-main.c ++++ b/src/miners/fs/tracker-main.c +@@ -39,6 +39,7 @@ + #include "tracker-miner-files.h" + #include "tracker-miner-files-index.h" + #include "tracker-writeback.h" ++#include "tracker-files-interface.h" + + #define ABOUT \ + "Tracker " PACKAGE_VERSION "\n" +@@ -668,6 +669,7 @@ main (gint argc, gchar *argv[]) + GDBusConnection *connection; + TrackerDomainOntology *domain_ontology; + gchar *domain_name, *dbus_name; ++ TrackerFilesInterface *files_interface; + + main_loop = NULL; + +@@ -723,6 +725,8 @@ main (gint argc, gchar *argv[]) + return EXIT_FAILURE; + } + ++ files_interface = tracker_files_interface_new (connection); ++ + /* Initialize logging */ + config = tracker_config_new (); + +@@ -871,6 +875,8 @@ main (gint argc, gchar *argv[]) + tracker_miner_files_set_need_mtime_check (FALSE); + } + ++ g_object_unref (files_interface); ++ + g_main_loop_unref (main_loop); + g_object_unref (config); + g_object_unref (miner_files_index); +diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am +index 05bb532a2..5b5b0227d 100644 +--- a/src/tracker-extract/Makefile.am ++++ b/src/tracker-extract/Makefile.am +@@ -533,8 +533,6 @@ libextract_dummy_la_LIBADD = \ + libexec_PROGRAMS = tracker-extract + + tracker_extract_SOURCES = \ +- tracker-config.c \ +- tracker-config.h \ + tracker-extract.c \ + tracker-extract.h \ + tracker-extract-controller.c \ +diff --git a/src/tracker-extract/meson.build b/src/tracker-extract/meson.build +index 9834dc422..7f0ccb699 100644 +--- a/src/tracker-extract/meson.build ++++ b/src/tracker-extract/meson.build +@@ -146,7 +146,6 @@ tracker_extract_priority_dbus = gnome.gdbus_codegen( + namespace: 'TrackerExtractDBus') + + tracker_extract_sources = [ +- 'tracker-config.c', + 'tracker-extract.c', + 'tracker-extract-controller.c', + 'tracker-extract-decorator.c', +diff --git a/src/tracker-extract/tracker-config.c b/src/tracker-extract/tracker-config.c +deleted file mode 100644 +index 20f6383f8..000000000 +--- a/src/tracker-extract/tracker-config.c ++++ /dev/null +@@ -1,328 +0,0 @@ +-/* +- * Copyright (C) 2009, Nokia +- * Copyright (C) 2014, Lanedo +- * +- * 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" +- +-#define G_SETTINGS_ENABLE_BACKEND +-#include +- +-#include +- +-#include "tracker-config.h" +- +-#define CONFIG_SCHEMA "org.freedesktop.Tracker.Extract" +-#define CONFIG_PATH "/org/freedesktop/tracker/extract/" +- +-static void config_set_property (GObject *object, +- guint param_id, +- const GValue *value, +- GParamSpec *pspec); +-static void config_get_property (GObject *object, +- guint param_id, +- GValue *value, +- GParamSpec *pspec); +-static void config_finalize (GObject *object); +-static void config_constructed (GObject *object); +- +-enum { +- PROP_0, +- PROP_VERBOSITY, +- PROP_SCHED_IDLE, +- PROP_MAX_BYTES, +- PROP_MAX_MEDIA_ART_WIDTH, +- PROP_WAIT_FOR_MINER_FS, +-}; +- +-G_DEFINE_TYPE (TrackerConfig, tracker_config, G_TYPE_SETTINGS); +- +-static void +-tracker_config_class_init (TrackerConfigClass *klass) +-{ +- GObjectClass *object_class = G_OBJECT_CLASS (klass); +- +- object_class->set_property = config_set_property; +- object_class->get_property = config_get_property; +- object_class->finalize = config_finalize; +- object_class->constructed = config_constructed; +- +- /* General */ +- g_object_class_install_property (object_class, +- PROP_VERBOSITY, +- g_param_spec_enum ("verbosity", +- "Log verbosity", +- "Log verbosity (0=errors, 1=minimal, 2=detailed, 3=debug)", +- TRACKER_TYPE_VERBOSITY, +- TRACKER_VERBOSITY_ERRORS, +- G_PARAM_READWRITE)); +- g_object_class_install_property (object_class, +- PROP_SCHED_IDLE, +- g_param_spec_enum ("sched-idle", +- "Scheduler priority when idle", +- "Scheduler priority when idle (0=always, 1=first-index, 2=never)", +- TRACKER_TYPE_SCHED_IDLE, +- TRACKER_SCHED_IDLE_FIRST_INDEX, +- G_PARAM_READWRITE)); +- +- g_object_class_install_property (object_class, +- PROP_MAX_BYTES, +- g_param_spec_int ("max-bytes", +- "Max Bytes", +- "Maximum number of UTF-8 bytes to extract per file [0->10485760]", +- 0, 1024 * 1024 * 10, +- 1024 * 1024, +- G_PARAM_READWRITE)); +- +- g_object_class_install_property (object_class, +- PROP_MAX_MEDIA_ART_WIDTH, +- g_param_spec_int ("max-media-art-width", +- "Max Media Art Width", +- " Maximum width of the Media Art to be generated (-1=disable, 0=original width, 1->2048=max pixel width)", +- -1, +- 2048, +- 0, +- G_PARAM_READWRITE)); +- +- g_object_class_install_property (object_class, +- PROP_WAIT_FOR_MINER_FS, +- g_param_spec_boolean ("wait-for-miner-fs", +- "Wait for FS miner to be done before extracting", +- "%TRUE to wait for tracker-miner-fs is done before extracting. %FAlSE otherwise", +- FALSE, +- G_PARAM_READWRITE)); +-} +- +-static void +-tracker_config_init (TrackerConfig *object) +-{ +-} +- +-static void +-config_set_property (GObject *object, +- guint param_id, +- const GValue *value, +- GParamSpec *pspec) +-{ +- TrackerConfig *config = TRACKER_CONFIG (object); +- +- switch (param_id) { +- /* General */ +- /* NOTE: We handle these because we have to be able +- * to save these based on command line overrides. +- */ +- case PROP_VERBOSITY: +- tracker_config_set_verbosity (config, g_value_get_enum (value)); +- break; +- +- /* We don't care about the others... we don't save anyway. */ +- case PROP_SCHED_IDLE: +- case PROP_MAX_BYTES: +- case PROP_MAX_MEDIA_ART_WIDTH: +- case PROP_WAIT_FOR_MINER_FS: +- break; +- +- default: +- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +- break; +- }; +-} +- +-static void +-config_get_property (GObject *object, +- guint param_id, +- GValue *value, +- GParamSpec *pspec) +-{ +- TrackerConfig *config = TRACKER_CONFIG (object); +- +- switch (param_id) { +- case PROP_VERBOSITY: +- g_value_set_enum (value, +- tracker_config_get_verbosity (config)); +- break; +- +- case PROP_SCHED_IDLE: +- g_value_set_enum (value, +- tracker_config_get_sched_idle (config)); +- break; +- +- case PROP_MAX_BYTES: +- g_value_set_int (value, +- tracker_config_get_max_bytes (config)); +- break; +- +- case PROP_MAX_MEDIA_ART_WIDTH: +- g_value_set_int (value, +- tracker_config_get_max_media_art_width (config)); +- break; +- +- case PROP_WAIT_FOR_MINER_FS: +- g_value_set_boolean (value, +- tracker_config_get_wait_for_miner_fs (config)); +- break; +- +- default: +- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +- break; +- }; +-} +- +-static void +-config_finalize (GObject *object) +-{ +- /* For now we do nothing here, we left this override in for +- * future expansion. +- */ +- +- (G_OBJECT_CLASS (tracker_config_parent_class)->finalize) (object); +-} +- +-static void +-config_constructed (GObject *object) +-{ +- GSettings *settings; +- +- (G_OBJECT_CLASS (tracker_config_parent_class)->constructed) (object); +- +- settings = G_SETTINGS (object); +- +- if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) { +- g_settings_delay (settings); +- } +- +- /* Set up bindings: +- * +- * What's interesting here is that 'verbosity' and +- * 'initial-sleep' are command line arguments that can be +- * overridden, so we don't update the config when we set them +- * from main() because it's a session configuration only, not +- * a permanent one. To do this we use the flag +- * G_SETTINGS_BIND_GET_NO_CHANGES. +- * +- * For the other settings, we don't bind the +- * G_SETTINGS_BIND_SET because we don't want to save anything, +- * ever, we only want to know about updates to the settings as +- * they're changed externally. The only time this may be +- * different is where we use the environment variable +- * TRACKER_USE_CONFIG_FILES and we want to write a config +- * file for convenience. But this is only necessary if the +- * config is different to the default. +- */ +- g_settings_bind (settings, "verbosity", object, "verbosity", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES); +- g_settings_bind (settings, "sched-idle", object, "sched-idle", G_SETTINGS_BIND_GET); +- g_settings_bind (settings, "max-media-art-width", object, "max-media-art-width", G_SETTINGS_BIND_GET); +- g_settings_bind (settings, "wait-for-miner-fs", object, "wait-for-miner-fs", G_SETTINGS_BIND_GET); +- +- /* Cache settings accessed from extractor modules, we don't want +- * the GSettings object accessed within these as it may trigger +- * unintended open() calls. +- */ +- TRACKER_CONFIG (settings)->max_bytes = g_settings_get_int (settings, "max-bytes"); +-} +- +-TrackerConfig * +-tracker_config_new (void) +-{ +- TrackerConfig *config = NULL; +- +- /* FIXME: should we unset GSETTINGS_BACKEND env var? */ +- +- if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) { +- GSettingsBackend *backend; +- gchar *filename, *basename; +- gboolean need_to_save; +- +- basename = g_strdup_printf ("%s.cfg", g_get_prgname ()); +- filename = g_build_filename (g_get_user_config_dir (), "tracker", basename, NULL); +- g_free (basename); +- +- need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE; +- +- backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General"); +- g_info ("Using config file '%s'", filename); +- g_free (filename); +- +- config = g_object_new (TRACKER_TYPE_CONFIG, +- "backend", backend, +- "schema-id", CONFIG_SCHEMA, +- "path", CONFIG_PATH, +- NULL); +- g_object_unref (backend); +- +- if (need_to_save) { +- g_info (" Config file does not exist, using default values..."); +- } +- } else { +- config = g_object_new (TRACKER_TYPE_CONFIG, +- "schema-id", CONFIG_SCHEMA, +- "path", CONFIG_PATH, +- NULL); +- } +- +- return config; +-} +- +-gint +-tracker_config_get_verbosity (TrackerConfig *config) +-{ +- g_return_val_if_fail (TRACKER_IS_CONFIG (config), TRACKER_VERBOSITY_ERRORS); +- +- return g_settings_get_enum (G_SETTINGS (config), "verbosity"); +-} +- +-void +-tracker_config_set_verbosity (TrackerConfig *config, +- gint value) +-{ +- g_return_if_fail (TRACKER_IS_CONFIG (config)); +- +- g_settings_set_enum (G_SETTINGS (config), "verbosity", value); +-} +- +-gint +-tracker_config_get_sched_idle (TrackerConfig *config) +-{ +- g_return_val_if_fail (TRACKER_IS_CONFIG (config), TRACKER_SCHED_IDLE_FIRST_INDEX); +- +- return g_settings_get_enum (G_SETTINGS (config), "sched-idle"); +-} +- +-gint +-tracker_config_get_max_bytes (TrackerConfig *config) +-{ +- g_return_val_if_fail (TRACKER_IS_CONFIG (config), 0); +- +- return config->max_bytes; +-} +- +-gint +-tracker_config_get_max_media_art_width (TrackerConfig *config) +-{ +- g_return_val_if_fail (TRACKER_IS_CONFIG (config), 0); +- +- return g_settings_get_int (G_SETTINGS (config), "max-media-art-width"); +-} +- +-gboolean +-tracker_config_get_wait_for_miner_fs (TrackerConfig *config) +-{ +- g_return_val_if_fail (TRACKER_IS_CONFIG (config), FALSE); +- +- return g_settings_get_boolean (G_SETTINGS (config), "wait-for-miner-fs"); +-} +diff --git a/src/tracker-extract/tracker-config.h b/src/tracker-extract/tracker-config.h +deleted file mode 100644 +index c8af8ef57..000000000 +--- a/src/tracker-extract/tracker-config.h ++++ /dev/null +@@ -1,61 +0,0 @@ +-/* +- * Copyright (C) 2009, Nokia +- * +- * 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_EXTRACT_CONFIG_H__ +-#define __TRACKER_EXTRACT_CONFIG_H__ +- +-#include +- +-G_BEGIN_DECLS +- +-#define TRACKER_TYPE_CONFIG (tracker_config_get_type ()) +-#define TRACKER_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONFIG, TrackerConfig)) +-#define TRACKER_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_CONFIG, TrackerConfigClass)) +-#define TRACKER_IS_CONFIG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONFIG)) +-#define TRACKER_IS_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_CONFIG)) +-#define TRACKER_CONFIG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONFIG, TrackerConfigClass)) +- +-typedef struct TrackerConfig TrackerConfig; +-typedef struct TrackerConfigClass TrackerConfigClass; +- +-struct TrackerConfig { +- GSettings parent; +- gint max_bytes; +-}; +- +-struct TrackerConfigClass { +- GSettingsClass parent_class; +-}; +- +-GType tracker_config_get_type (void) G_GNUC_CONST; +- +-TrackerConfig *tracker_config_new (void); +-gint tracker_config_get_verbosity (TrackerConfig *config); +-gint tracker_config_get_sched_idle (TrackerConfig *config); +-gint tracker_config_get_max_bytes (TrackerConfig *config); +-gint tracker_config_get_max_media_art_width (TrackerConfig *config); +-gboolean tracker_config_get_wait_for_miner_fs (TrackerConfig *config); +- +-void tracker_config_set_verbosity (TrackerConfig *config, +- gint value); +- +-G_END_DECLS +- +-#endif /* __TRACKER_EXTRACT_CONFIG_H__ */ +- +diff --git a/src/tracker-extract/tracker-extract-controller.c b/src/tracker-extract/tracker-extract-controller.c +index 3a34a8dbf..01a2ae4f7 100644 +--- a/src/tracker-extract/tracker-extract-controller.c ++++ b/src/tracker-extract/tracker-extract-controller.c +@@ -32,17 +32,78 @@ struct TrackerExtractControllerPrivate { + TrackerDecorator *decorator; + GCancellable *cancellable; + GDBusConnection *connection; ++ GDBusProxy *miner_proxy; + gint paused; + }; + + G_DEFINE_TYPE (TrackerExtractController, tracker_extract_controller, G_TYPE_OBJECT) + ++static void ++update_extract_config (TrackerExtractController *controller, ++ GDBusProxy *proxy) ++{ ++ TrackerExtractControllerPrivate *priv; ++ GVariantIter iter; ++ g_autoptr (GVariant) v = NULL; ++ GVariant *value; ++ gchar *key; ++ ++ priv = tracker_extract_controller_get_instance_private (controller); ++ ++ v = g_dbus_proxy_get_cached_property (proxy, "ExtractorConfig"); ++ if (!v) ++ return; ++ ++ g_variant_iter_init (&iter, v); ++ ++ while (g_variant_iter_next (&iter, "{sv}", &key, &value)) { ++ if (g_strcmp0 (key, "max-bytes") == 0 && ++ g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) { ++ TrackerExtract *extract = NULL; ++ gint max_bytes; ++ ++ max_bytes = g_variant_get_int32 (value); ++ g_object_get (priv->decorator, "extractor", &extract, NULL); ++ ++ if (extract) { ++ tracker_extract_set_max_text (extract, max_bytes); ++ g_object_unref (extract); ++ } ++ } ++ ++ g_free (key); ++ g_variant_unref (value); ++ } ++} ++ ++static void ++miner_properties_changed_cb (GDBusProxy *proxy, ++ GVariant *changed_properties, ++ GStrv invalidated_properties, ++ gpointer user_data) ++{ ++ update_extract_config (user_data, proxy); ++} ++ + static void + tracker_extract_controller_constructed (GObject *object) + { + TrackerExtractController *self = (TrackerExtractController *) object; + + G_OBJECT_CLASS (tracker_extract_controller_parent_class)->constructed (object); ++ ++ self->priv->miner_proxy = g_dbus_proxy_new_sync (self->priv->connection, ++ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, ++ NULL, ++ "org.freedesktop.Tracker3.Miner.Files", ++ "/org/freedesktop/Tracker3/Files", ++ "org.freedesktop.Tracker3.Files", ++ NULL, NULL); ++ if (self->priv->miner_proxy) { ++ g_signal_connect (self->priv->miner_proxy, "g-properties-changed", ++ G_CALLBACK (miner_properties_changed_cb), self); ++ update_extract_config (self, self->priv->miner_proxy); ++ } + } + + static void +diff --git a/src/tracker-extract/tracker-extract-epub.c b/src/tracker-extract/tracker-extract-epub.c +index 2e65e10bd..8bd945738 100644 +--- a/src/tracker-extract/tracker-extract-epub.c ++++ b/src/tracker-extract/tracker-extract-epub.c +@@ -561,12 +561,12 @@ extract_opf_path (const gchar *uri) + } + + static gchar * +-extract_opf_contents (const gchar *uri, +- const gchar *content_prefix, +- GList *content_files) ++extract_opf_contents (TrackerExtractInfo *info, ++ const gchar *uri, ++ const gchar *content_prefix, ++ GList *content_files) + { + OPFContentData content_data = { 0 }; +- TrackerConfig *config; + GError *error = NULL; + GList *l; + GMarkupParser xml_parser = { +@@ -575,10 +575,8 @@ extract_opf_contents (const gchar *uri, + NULL, NULL + }; + +- config = tracker_main_get_config (); +- + content_data.contents = g_string_new (""); +- content_data.limit = (gsize) tracker_config_get_max_bytes (config); ++ content_data.limit = (gsize) tracker_extract_info_get_max_text (info); + + g_debug ("Extracting up to %" G_GSIZE_FORMAT " bytes of content", content_data.limit); + +@@ -611,8 +609,9 @@ extract_opf_contents (const gchar *uri, + } + + static TrackerResource * +-extract_opf (const gchar *uri, +- const gchar *opf_path) ++extract_opf (TrackerExtractInfo *info, ++ const gchar *uri, ++ const gchar *opf_path) + { + TrackerResource *ebook; + GMarkupParseContext *context; +@@ -652,7 +651,7 @@ extract_opf (const gchar *uri, + } + + dirname = g_path_get_dirname (opf_path); +- contents = extract_opf_contents (uri, dirname, data->pages); ++ contents = extract_opf_contents (info, uri, dirname, data->pages); + g_free (dirname); + + if (contents && *contents) { +@@ -682,7 +681,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *info) + return FALSE; + } + +- ebook = extract_opf (uri, opf_path); ++ ebook = extract_opf (info, uri, opf_path); + g_free (opf_path); + g_free (uri); + +diff --git a/src/tracker-extract/tracker-extract-html.c b/src/tracker-extract/tracker-extract-html.c +index 6fb030ff5..8390cef3b 100644 +--- a/src/tracker-extract/tracker-extract-html.c ++++ b/src/tracker-extract/tracker-extract-html.c +@@ -233,7 +233,6 @@ tracker_extract_get_metadata (TrackerExtractInfo *info) + { + TrackerResource *metadata; + GFile *file; +- TrackerConfig *config; + htmlDocPtr doc; + parser_data pd; + gchar *filename; +@@ -283,8 +282,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *info) + pd.plain_text = g_string_new (NULL); + pd.title = g_string_new (NULL); + +- config = tracker_main_get_config (); +- pd.n_bytes_remaining = tracker_config_get_max_bytes (config); ++ pd.n_bytes_remaining = tracker_extract_info_get_max_text (info); + + filename = g_file_get_path (file); + doc = htmlSAXParseFile (filename, NULL, &handler, &pd); +diff --git a/src/tracker-extract/tracker-extract-msoffice-xml.c b/src/tracker-extract/tracker-extract-msoffice-xml.c +index b45667e33..e58ea83e8 100644 +--- a/src/tracker-extract/tracker-extract-msoffice-xml.c ++++ b/src/tracker-extract/tracker-extract-msoffice-xml.c +@@ -814,7 +814,6 @@ tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + MsOfficeXMLParserInfo info = { 0 }; + MsOfficeXMLFileType file_type; + TrackerResource *metadata; +- TrackerConfig *config; + GMarkupParseContext *context = NULL; + GError *error = NULL; + GFile *file; +@@ -830,9 +829,6 @@ tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + /* Get current Content Type */ + file_type = msoffice_xml_get_file_type (uri); + +- /* Setup conf */ +- config = tracker_main_get_config (); +- + g_debug ("Extracting MsOffice XML format..."); + + metadata = tracker_resource_new (NULL); +@@ -848,7 +844,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + info.content = NULL; + info.title_already_set = FALSE; + info.generator_already_set = FALSE; +- info.bytes_pending = tracker_config_get_max_bytes (config); ++ info.bytes_pending = tracker_extract_info_get_max_text (extract_info); + + /* Create content-type parser context */ + context = g_markup_parse_context_new (&content_types_parser, +diff --git a/src/tracker-extract/tracker-extract-msoffice.c b/src/tracker-extract/tracker-extract-msoffice.c +index 289dc9899..5516071dd 100644 +--- a/src/tracker-extract/tracker-extract-msoffice.c ++++ b/src/tracker-extract/tracker-extract-msoffice.c +@@ -1623,7 +1623,6 @@ G_MODULE_EXPORT gboolean + tracker_extract_get_metadata (TrackerExtractInfo *info) + { + TrackerResource *metadata; +- TrackerConfig *config; + GsfInfile *infile = NULL; + gchar *content = NULL, *uri; + gboolean is_encrypted = FALSE; +@@ -1670,8 +1669,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *info) + extract_summary (metadata, infile, uri); + + /* Set max bytes to read from content */ +- config = tracker_main_get_config (); +- max_bytes = tracker_config_get_max_bytes (config); ++ max_bytes = tracker_extract_info_get_max_text (info); + + if (g_ascii_strcasecmp (mime_used, "application/msword") == 0) { + /* Word file */ +diff --git a/src/tracker-extract/tracker-extract-oasis.c b/src/tracker-extract/tracker-extract-oasis.c +index 1dd977c29..c3187e49f 100644 +--- a/src/tracker-extract/tracker-extract-oasis.c ++++ b/src/tracker-extract/tracker-extract-oasis.c +@@ -168,7 +168,6 @@ G_MODULE_EXPORT gboolean + tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + { + TrackerResource *metadata; +- TrackerConfig *config; + ODTMetadataParseInfo info = { 0 }; + ODTFileType file_type; + GFile *file; +@@ -193,9 +192,6 @@ tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + file = tracker_extract_info_get_file (extract_info); + uri = g_file_get_uri (file); + +- /* Setup conf */ +- config = tracker_main_get_config (); +- + g_debug ("Extracting OASIS metadata and contents from '%s'", uri); + + /* First, parse metadata */ +@@ -230,7 +226,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *extract_info) + + /* Extract content with the given limitations */ + extract_oasis_content (uri, +- tracker_config_get_max_bytes (config), ++ tracker_extract_info_get_max_text (extract_info), + file_type, + metadata); + +diff --git a/src/tracker-extract/tracker-extract-pdf.c b/src/tracker-extract/tracker-extract-pdf.c +index a91fe63e9..e6d6e1ef6 100644 +--- a/src/tracker-extract/tracker-extract-pdf.c ++++ b/src/tracker-extract/tracker-extract-pdf.c +@@ -280,7 +280,6 @@ write_pdf_data (PDFData data, + G_MODULE_EXPORT gboolean + tracker_extract_get_metadata (TrackerExtractInfo *info) + { +- TrackerConfig *config; + GTime creation_date; + GError *error = NULL; + TrackerResource *metadata; +@@ -522,8 +521,7 @@ tracker_extract_get_metadata (TrackerExtractInfo *info) + + tracker_resource_set_int64 (metadata, "nfo:pageCount", poppler_document_get_n_pages(document)); + +- config = tracker_main_get_config (); +- n_bytes = tracker_config_get_max_bytes (config); ++ n_bytes = tracker_extract_info_get_max_text (info); + content = extract_content_text (document, n_bytes); + + if (content) { +diff --git a/src/tracker-extract/tracker-extract-text.c b/src/tracker-extract/tracker-extract-text.c +index 5f94d7309..4c4a6cca0 100644 +--- a/src/tracker-extract/tracker-extract-text.c ++++ b/src/tracker-extract/tracker-extract-text.c +@@ -84,13 +84,10 @@ G_MODULE_EXPORT gboolean + tracker_extract_get_metadata (TrackerExtractInfo *info) + { + TrackerResource *metadata; +- TrackerConfig *config; + gchar *content; + +- config = tracker_main_get_config (); +- + content = get_file_content (tracker_extract_info_get_file (info), +- tracker_config_get_max_bytes (config)); ++ tracker_extract_info_get_max_text (info)); + + metadata = tracker_resource_new (NULL); + tracker_resource_add_uri (metadata, "rdf:type", "nfo:PlainTextDocument"); +diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c +index ec08d050d..cd0511e8f 100644 +--- a/src/tracker-extract/tracker-extract.c ++++ b/src/tracker-extract/tracker-extract.c +@@ -45,6 +45,8 @@ + + G_DEFINE_QUARK (TrackerExtractError, tracker_extract_error) + ++#define DEFAULT_MAX_TEXT 1048576 ++ + extern gboolean debug; + + typedef struct { +@@ -56,6 +58,8 @@ typedef struct { + GHashTable *statistics_data; + GList *running_tasks; + ++ gint max_text; ++ + /* used to maintain the running tasks + * and stats from different threads + */ +@@ -83,6 +87,7 @@ typedef struct { + GAsyncResult *res; + gchar *file; + gchar *mimetype; ++ gint max_text; + + TrackerMimetypeInfo *mimetype_handlers; + +@@ -129,6 +134,7 @@ tracker_extract_init (TrackerExtract *object) + priv->statistics_data = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) statistics_data_free); + priv->single_thread_extractors = g_hash_table_new (NULL, NULL); ++ priv->max_text = DEFAULT_MAX_TEXT; + priv->thread_pool = g_thread_pool_new ((GFunc) get_metadata, + NULL, 10, TRUE, NULL); + +@@ -277,7 +283,7 @@ get_file_metadata (TrackerExtractTask *task, + *info_out = NULL; + + file = g_file_new_for_uri (task->file); +- info = tracker_extract_info_new (file, task->mimetype); ++ info = tracker_extract_info_new (file, task->mimetype, task->max_text); + g_object_unref (file); + + if (task->mimetype && *task->mimetype) { +@@ -345,6 +351,7 @@ extract_task_new (TrackerExtract *extract, + GAsyncResult *res, + GError **error) + { ++ TrackerExtractPrivate *priv = TRACKER_EXTRACT_GET_PRIVATE (extract); + TrackerExtractTask *task; + gchar *mimetype_used; + +@@ -381,6 +388,7 @@ extract_task_new (TrackerExtract *extract, + task->file = g_strdup (uri); + task->mimetype = mimetype_used; + task->extract = extract; ++ task->max_text = priv->max_text; + + if (task->cancellable) { + task->signal_id = g_cancellable_connect (cancellable, +@@ -779,3 +787,12 @@ tracker_extract_file_finish (TrackerExtract *extract, + + return g_task_propagate_pointer (G_TASK (res), error); + } ++ ++void ++tracker_extract_set_max_text (TrackerExtract *extract, ++ gint max_text) ++{ ++ TrackerExtractPrivate *priv = TRACKER_EXTRACT_GET_PRIVATE (extract); ++ ++ priv->max_text = max_text; ++} +diff --git a/src/tracker-extract/tracker-extract.h b/src/tracker-extract/tracker-extract.h +index 06aae9578..66271805b 100644 +--- a/src/tracker-extract/tracker-extract.h ++++ b/src/tracker-extract/tracker-extract.h +@@ -73,6 +73,9 @@ TrackerExtractInfo * + void tracker_extract_dbus_start (TrackerExtract *extract); + void tracker_extract_dbus_stop (TrackerExtract *extract); + ++void tracker_extract_set_max_text (TrackerExtract *extract, ++ gint max_text); ++ + /* Not DBus API */ + void tracker_extract_get_metadata_by_cmdline (TrackerExtract *object, + const gchar *path, +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 7732f443d..92333c62f 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -40,7 +40,6 @@ + + #include + +-#include "tracker-config.h" + #include "tracker-main.h" + #include "tracker-extract.h" + #include "tracker-extract-controller.h" +@@ -74,8 +73,6 @@ static gboolean version; + static gchar *domain_ontology_name = NULL; + static guint shutdown_timeout_id = 0; + +-static TrackerConfig *config; +- + static GOptionEntry entries[] = { + { "verbosity", 'v', 0, + G_OPTION_ARG_INT, &verbosity, +@@ -164,26 +161,8 @@ log_handler (const gchar *domain, + } + } + +-static void +-sanity_check_option_values (TrackerConfig *config) +-{ +- g_message ("General options:"); +- g_message (" Verbosity ............................ %d", +- tracker_config_get_verbosity (config)); +- g_message (" Sched Idle ........................... %d", +- tracker_config_get_sched_idle (config)); +- g_message (" Max bytes (per file) ................. %d", +- tracker_config_get_max_bytes (config)); +-} +- +-TrackerConfig * +-tracker_main_get_config (void) +-{ +- return config; +-} +- + static int +-run_standalone (TrackerConfig *config) ++run_standalone (void) + { + TrackerExtract *object; + GFile *file; +@@ -217,7 +196,7 @@ run_standalone (TrackerConfig *config) + tracker_locale_sanity_check (); + + /* This makes sure we don't steal all the system's resources */ +- initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), TRUE); ++ initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, TRUE); + + file = g_file_new_for_commandline_arg (filename); + uri = g_file_get_uri (file); +@@ -353,33 +332,23 @@ main (int argc, char *argv[]) + return EXIT_FAILURE; + } + +- config = tracker_config_new (); +- +- /* Extractor command line arguments */ +- if (verbosity > -1) { +- tracker_config_set_verbosity (config, verbosity); +- } +- +- tracker_log_init (tracker_config_get_verbosity (config), &log_filename); ++ tracker_log_init (MAX (verbosity, 0), &log_filename); + if (log_filename != NULL) { + g_message ("Using log file:'%s'", log_filename); + g_free (log_filename); + } + +- sanity_check_option_values (config); +- + /* Set conditions when we use stand alone settings */ + if (filename) { +- return run_standalone (config); ++ return run_standalone (); + } + + /* This makes sure we don't steal all the system's resources */ +- initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), TRUE); ++ initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, TRUE); + + extract = tracker_extract_new (TRUE, force_module); + + if (!extract) { +- g_object_unref (config); + tracker_log_shutdown (); + return EXIT_FAILURE; + } +@@ -390,7 +359,6 @@ main (int argc, char *argv[]) + + if (error) { + g_critical ("Could not start decorator: %s\n", error->message); +- g_object_unref (config); + tracker_log_shutdown (); + return EXIT_FAILURE; + } +@@ -400,7 +368,6 @@ main (int argc, char *argv[]) + g_critical ("Could not create miner DBus proxy: %s\n", error->message); + g_error_free (error); + g_object_unref (decorator); +- g_object_unref (config); + tracker_log_shutdown (); + return EXIT_FAILURE; + } +@@ -464,7 +431,5 @@ main (int argc, char *argv[]) + + tracker_log_shutdown (); + +- g_object_unref (config); +- + return EXIT_SUCCESS; + } +diff --git a/src/tracker-extract/tracker-main.h b/src/tracker-extract/tracker-main.h +index 4af2e3e06..5ee12c697 100644 +--- a/src/tracker-extract/tracker-main.h ++++ b/src/tracker-extract/tracker-main.h +@@ -21,13 +21,8 @@ + #ifndef __TRACKER_MAIN_H__ + #define __TRACKER_MAIN_H__ + +-#include "tracker-config.h" +- + G_BEGIN_DECLS + +-/* Enables getting the config object from extractors */ +-TrackerConfig *tracker_main_get_config (void); +- + G_END_DECLS + + #endif /* __TRACKER_MAIN_H__ */ +diff --git a/tests/libtracker-extract/tracker-extract-info-test.c b/tests/libtracker-extract/tracker-extract-info-test.c +index d189d44c3..b364254cc 100644 +--- a/tests/libtracker-extract/tracker-extract-info-test.c ++++ b/tests/libtracker-extract/tracker-extract-info-test.c +@@ -29,7 +29,7 @@ test_extract_info_setters (void) + + file = g_file_new_for_path ("./imaginary-file-2"); + +- info = tracker_extract_info_new (file, "imaginary/mime"); ++ info = tracker_extract_info_new (file, "imaginary/mime", 100); + info_ref = tracker_extract_info_ref (info); + + g_assert (g_file_equal (file, tracker_extract_info_get_file (info))); +@@ -50,7 +50,7 @@ test_extract_info_empty_objects (void) + + file = g_file_new_for_path ("./imaginary-file"); + +- info = tracker_extract_info_new (file, "imaginary/mime"); ++ info = tracker_extract_info_new (file, "imaginary/mime", 100); + info_ref = tracker_extract_info_ref (info); + + tracker_extract_info_unref (info_ref); +-- +2.43.0 + + +From 6917c65c66338dd6b14bdfbfa301785997648b4d Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 24 Sep 2023 19:18:52 +0200 +Subject: [PATCH 04/22] tracker-extract: Avoid file access for persistence + +Use a memfd_create() FD, maintained and kept alive by tracker-miner-fs-3. +This FD is obtained through D-Bus, and used for temporary storage. Since +processing of files in the extractor is largely linear nowadays, this +also simplifies the persistent storage to store a single file. +--- + config.h.meson.in | 3 + + meson.build | 1 + + src/miners/fs/tracker-files-interface.c | 72 ++++- + .../tracker-extract-controller.c | 65 ++++- + .../tracker-extract-controller.h | 5 +- + .../tracker-extract-decorator.c | 98 ++++--- + .../tracker-extract-decorator.h | 2 + + .../tracker-extract-persistence.c | 267 +++++------------- + .../tracker-extract-persistence.h | 19 +- + src/tracker-extract/tracker-main.c | 9 +- + 10 files changed, 273 insertions(+), 268 deletions(-) + +diff --git a/config.h.meson.in b/config.h.meson.in +index 176088724..78e6cd2bc 100644 +--- a/config.h.meson.in ++++ b/config.h.meson.in +@@ -87,6 +87,9 @@ + /* Define to 0 if tracker FTS is not compiled */ + #mesondefine HAVE_TRACKER_FTS + ++/* Define to 1 if you have the `memfd_create' function. */ ++#mesondefine HAVE_MEMFD_CREATE ++ + /* Define if we have UPOWER */ + #mesondefine HAVE_UPOWER + +diff --git a/meson.build b/meson.build +index fd536f2e6..1812daa1b 100644 +--- a/meson.build ++++ b/meson.build +@@ -320,6 +320,7 @@ conf.set('HAVE_GETLINE', cc.has_function('getline', prefix : '#include + conf.set('HAVE_POSIX_FADVISE', cc.has_function('posix_fadvise', prefix : '#include ')) + 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('LOCALEDIR', '"@0@/@1@"'.format(get_option('prefix'), get_option('localedir'))) + conf.set('SHAREDIR', '"@0@/@1@"'.format(get_option('prefix'), get_option('datadir'))) +diff --git a/src/miners/fs/tracker-files-interface.c b/src/miners/fs/tracker-files-interface.c +index 0e259a6ce..ee2c1b985 100644 +--- a/src/miners/fs/tracker-files-interface.c ++++ b/src/miners/fs/tracker-files-interface.c +@@ -23,12 +23,16 @@ + + #include "tracker-files-interface.h" + ++#include ++#include ++ + struct _TrackerFilesInterface + { + GObject parent_instance; + GDBusConnection *connection; + GSettings *settings; + guint object_id; ++ int fd; + }; + + enum { +@@ -43,6 +47,9 @@ static const gchar *introspection_xml = + "" + " " + " " ++ " " ++ " " ++ " " + " " + ""; + +@@ -53,6 +60,66 @@ tracker_files_interface_init (TrackerFilesInterface *files_interface) + { + } + ++static void ++handle_method_call (GDBusConnection *connection, ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *method_name, ++ GVariant *parameters, ++ GDBusMethodInvocation *invocation, ++ gpointer user_data) ++{ ++ TrackerFilesInterface *files_interface = user_data; ++ ++ if (g_strcmp0 (method_name, "GetPersistenceStorage") == 0) { ++ GVariant *out_parameters; ++ g_autoptr (GUnixFDList) fd_list = NULL; ++ g_autoptr (GError) error = NULL; ++ int idx; ++ ++ if (files_interface->fd <= 0) { ++#ifdef HAVE_MEMFD_CREATE ++ files_interface->fd = memfd_create ("extract-persistent-storage", ++ MFD_CLOEXEC); ++#else ++ g_autofree gchar *path = NULL; ++ ++ path = g_strdup_printf ("%s/tracker-persistence.XXXXXX", ++ g_get_tmp_dir ()); ++ files_interface->fd = g_mkstemp_full (path, 0, 0600); ++ unlink (path); ++#endif ++ ++ if (files_interface->fd < 0) { ++ g_dbus_method_invocation_return_error (invocation, ++ G_IO_ERROR, ++ G_IO_ERROR_FAILED, ++ "Could not create memfd"); ++ return; ++ } ++ } ++ ++ fd_list = g_unix_fd_list_new (); ++ idx = g_unix_fd_list_append (fd_list, files_interface->fd, &error); ++ ++ if (error) { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ } else { ++ out_parameters = g_variant_new ("(h)", idx); ++ g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, ++ out_parameters, ++ fd_list); ++ } ++ } else { ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_UNKNOWN_METHOD, ++ "Unknown method %s", ++ method_name); ++ } ++} ++ + static GVariant * + handle_get_property (GDBusConnection *connection, + const gchar *sender, +@@ -90,7 +157,7 @@ static void + tracker_files_interface_constructed (GObject *object) + { + TrackerFilesInterface *files_interface = TRACKER_FILES_INTERFACE (object); +- GDBusInterfaceVTable vtable = { NULL, handle_get_property, NULL }; ++ GDBusInterfaceVTable vtable = { handle_method_call, handle_get_property, NULL }; + g_autoptr (GDBusNodeInfo) introspection_data = NULL; + + G_OBJECT_CLASS (tracker_files_interface_parent_class)->constructed (object); +@@ -115,6 +182,9 @@ tracker_files_interface_finalize (GObject *object) + g_clear_object (&files_interface->connection); + g_clear_object (&files_interface->settings); + ++ if (files_interface->fd) ++ close (files_interface->fd); ++ + G_OBJECT_CLASS (tracker_files_interface_parent_class)->finalize (object); + } + +diff --git a/src/tracker-extract/tracker-extract-controller.c b/src/tracker-extract/tracker-extract-controller.c +index 01a2ae4f7..1affb0ef8 100644 +--- a/src/tracker-extract/tracker-extract-controller.c ++++ b/src/tracker-extract/tracker-extract-controller.c +@@ -23,13 +23,17 @@ + + #include "tracker-main.h" + ++#include ++ + enum { + PROP_DECORATOR = 1, + PROP_CONNECTION, ++ PROP_PERSISTENCE, + }; + + struct TrackerExtractControllerPrivate { + TrackerDecorator *decorator; ++ TrackerExtractPersistence *persistence; + GCancellable *cancellable; + GDBusConnection *connection; + GDBusProxy *miner_proxy; +@@ -85,6 +89,38 @@ miner_properties_changed_cb (GDBusProxy *proxy, + update_extract_config (user_data, proxy); + } + ++static gboolean ++set_up_persistence (TrackerExtractController *controller, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ TrackerExtractControllerPrivate *priv = ++ tracker_extract_controller_get_instance_private (controller); ++ g_autoptr (GUnixFDList) out_fd_list = NULL; ++ g_autoptr (GVariant) variant = NULL; ++ int idx, fd; ++ ++ variant = g_dbus_proxy_call_with_unix_fd_list_sync (priv->miner_proxy, ++ "GetPersistenceStorage", ++ NULL, ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, ++ NULL, ++ &out_fd_list, ++ cancellable, ++ error); ++ if (!variant) ++ return FALSE; ++ ++ g_variant_get (variant, "(h)", &idx); ++ fd = g_unix_fd_list_get (out_fd_list, idx, error); ++ if (fd < 0) ++ return FALSE; ++ ++ tracker_extract_persistence_set_fd (priv->persistence, fd); ++ return TRUE; ++} ++ + static void + tracker_extract_controller_constructed (GObject *object) + { +@@ -104,6 +140,8 @@ tracker_extract_controller_constructed (GObject *object) + G_CALLBACK (miner_properties_changed_cb), self); + update_extract_config (self, self->priv->miner_proxy); + } ++ ++ set_up_persistence (self, NULL, NULL); + } + + static void +@@ -121,6 +159,12 @@ tracker_extract_controller_get_property (GObject *object, + case PROP_CONNECTION: + g_value_set_object (value, self->priv->connection); + break; ++ case PROP_PERSISTENCE: ++ g_value_set_object (value, self->priv->persistence); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; + } + } + +@@ -140,6 +184,12 @@ tracker_extract_controller_set_property (GObject *object, + case PROP_CONNECTION: + self->priv->connection = g_value_dup_object (value); + break; ++ case PROP_PERSISTENCE: ++ self->priv->persistence = g_value_dup_object (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; + } + } + +@@ -149,6 +199,7 @@ tracker_extract_controller_dispose (GObject *object) + TrackerExtractController *self = (TrackerExtractController *) object; + + g_clear_object (&self->priv->decorator); ++ g_clear_object (&self->priv->persistence); + + G_OBJECT_CLASS (tracker_extract_controller_parent_class)->dispose (object); + } +@@ -181,6 +232,14 @@ tracker_extract_controller_class_init (TrackerExtractControllerClass *klass) + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); ++ g_object_class_install_property (object_class, ++ PROP_PERSISTENCE, ++ g_param_spec_object ("persistence", ++ NULL, NULL, ++ TRACKER_TYPE_EXTRACT_PERSISTENCE, ++ G_PARAM_STATIC_STRINGS | ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, + sizeof (TrackerExtractControllerPrivate)); +@@ -195,13 +254,15 @@ tracker_extract_controller_init (TrackerExtractController *self) + } + + TrackerExtractController * +-tracker_extract_controller_new (TrackerDecorator *decorator, +- GDBusConnection *connection) ++tracker_extract_controller_new (TrackerDecorator *decorator, ++ GDBusConnection *connection, ++ TrackerExtractPersistence *persistence) + { + g_return_val_if_fail (TRACKER_IS_DECORATOR (decorator), NULL); + + return g_object_new (TRACKER_TYPE_EXTRACT_CONTROLLER, + "decorator", decorator, + "connection", connection, ++ "persistence", persistence, + NULL); + } +diff --git a/src/tracker-extract/tracker-extract-controller.h b/src/tracker-extract/tracker-extract-controller.h +index 7d8a70816..3ba85751c 100644 +--- a/src/tracker-extract/tracker-extract-controller.h ++++ b/src/tracker-extract/tracker-extract-controller.h +@@ -47,8 +47,9 @@ struct TrackerExtractControllerClass { + }; + + GType tracker_extract_controller_get_type (void) G_GNUC_CONST; +-TrackerExtractController * tracker_extract_controller_new (TrackerDecorator *decorator, +- GDBusConnection *connection); ++TrackerExtractController * tracker_extract_controller_new (TrackerDecorator *decorator, ++ GDBusConnection *connection, ++ TrackerExtractPersistence *persistence); + + G_END_DECLS + +diff --git a/src/tracker-extract/tracker-extract-decorator.c b/src/tracker-extract/tracker-extract-decorator.c +index 516e1ee48..e2575d662 100644 +--- a/src/tracker-extract/tracker-extract-decorator.c ++++ b/src/tracker-extract/tracker-extract-decorator.c +@@ -27,7 +27,9 @@ + #include "tracker-extract-priority-dbus.h" + + enum { +- PROP_EXTRACTOR = 1 ++ PROP_0, ++ PROP_EXTRACTOR, ++ PROP_PERSISTENCE, + }; + + #define TRACKER_EXTRACT_DATA_SOURCE TRACKER_PREFIX_TRACKER "extractor-data-source" +@@ -51,7 +53,6 @@ struct _TrackerExtractDecoratorPrivate { + guint n_extracting_files; + + TrackerExtractPersistence *persistence; +- GHashTable *recovery_files; + + /* DBus name -> AppData */ + GHashTable *apps; +@@ -82,6 +83,9 @@ static GInitableIface *parent_initable_iface; + static void decorator_get_next_file (TrackerDecorator *decorator); + static void tracker_extract_decorator_initable_iface_init (GInitableIface *iface); + ++static void decorator_ignore_file (GFile *file, ++ gpointer user_data); ++ + G_DEFINE_TYPE_WITH_CODE (TrackerExtractDecorator, tracker_extract_decorator, + TRACKER_TYPE_DECORATOR_FS, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, tracker_extract_decorator_initable_iface_init)) +@@ -100,6 +104,12 @@ tracker_extract_decorator_get_property (GObject *object, + case PROP_EXTRACTOR: + g_value_set_object (value, priv->extractor); + break; ++ case PROP_PERSISTENCE: ++ g_value_set_object (value, priv->persistence); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; + } + } + +@@ -117,6 +127,12 @@ tracker_extract_decorator_set_property (GObject *object, + case PROP_EXTRACTOR: + priv->extractor = g_value_dup_object (value); + break; ++ case PROP_PERSISTENCE: ++ priv->persistence = g_value_dup_object (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; + } + } + +@@ -135,7 +151,7 @@ tracker_extract_decorator_finalize (GObject *object) + + g_object_unref (priv->iface); + g_hash_table_unref (priv->apps); +- g_hash_table_unref (priv->recovery_files); ++ g_object_unref (priv->persistence); + + G_OBJECT_CLASS (tracker_extract_decorator_parent_class)->finalize (object); + } +@@ -183,8 +199,7 @@ get_metadata_cb (TrackerExtract *extract, + priv = TRACKER_EXTRACT_DECORATOR (data->decorator)->priv; + info = tracker_extract_file_finish (extract, result, &error); + +- tracker_extract_persistence_remove_file (priv->persistence, data->file); +- g_hash_table_remove (priv->recovery_files, tracker_decorator_info_get_url (data->decorator_info)); ++ tracker_extract_persistence_set_file (priv->persistence, NULL); + + if (error) { + g_message ("Extraction failed: %s\n", error ? error->message : "no error given"); +@@ -214,26 +229,6 @@ get_metadata_cb (TrackerExtract *extract, + g_free (data); + } + +-static GFile * +-decorator_get_recovery_file (TrackerExtractDecorator *decorator, +- TrackerDecoratorInfo *info) +-{ +- TrackerExtractDecoratorPrivate *priv; +- GFile *file; +- +- priv = decorator->priv; +- file = g_hash_table_lookup (priv->recovery_files, +- tracker_decorator_info_get_url (info)); +- +- if (file) { +- g_object_ref (file); +- } else { +- file = g_file_new_for_uri (tracker_decorator_info_get_url (info)); +- } +- +- return file; +-} +- + static void + decorator_next_item_cb (TrackerDecorator *decorator, + GAsyncResult *result, +@@ -277,12 +272,12 @@ decorator_next_item_cb (TrackerDecorator *decorator, + data = g_new0 (ExtractData, 1); + data->decorator = decorator; + data->decorator_info = info; +- data->file = decorator_get_recovery_file (TRACKER_EXTRACT_DECORATOR (decorator), info); ++ data->file = g_file_new_for_uri (tracker_decorator_info_get_url (info)); + task = tracker_decorator_info_get_task (info); + + g_message ("Extracting metadata for '%s'", tracker_decorator_info_get_url (info)); + +- tracker_extract_persistence_add_file (priv->persistence, data->file); ++ tracker_extract_persistence_set_file (priv->persistence, data->file); + + tracker_extract_file (priv->extractor, + tracker_decorator_info_get_url (info), +@@ -341,6 +336,22 @@ tracker_extract_decorator_resumed (TrackerMiner *miner) + decorator_get_next_file (TRACKER_DECORATOR (miner)); + } + ++static void ++tracker_extract_decorator_started (TrackerMiner *miner) ++{ ++ TrackerExtractDecorator *decorator = TRACKER_EXTRACT_DECORATOR (miner); ++ TrackerExtractDecoratorPrivate *priv = ++ tracker_extract_decorator_get_instance_private (decorator); ++ GFile *file; ++ ++ file = tracker_extract_persistence_get_file (priv->persistence); ++ ++ if (file) ++ decorator_ignore_file (file, decorator); ++ ++ TRACKER_MINER_CLASS (tracker_extract_decorator_parent_class)->started (miner); ++} ++ + static void + tracker_extract_decorator_items_available (TrackerDecorator *decorator) + { +@@ -544,6 +555,7 @@ tracker_extract_decorator_class_init (TrackerExtractDecoratorClass *klass) + + miner_class->paused = tracker_extract_decorator_paused; + miner_class->resumed = tracker_extract_decorator_resumed; ++ miner_class->started = tracker_extract_decorator_started; + + decorator_class->items_available = tracker_extract_decorator_items_available; + decorator_class->finished = tracker_extract_decorator_finished; +@@ -555,25 +567,21 @@ tracker_extract_decorator_class_init (TrackerExtractDecoratorClass *klass) + "Extractor", + TRACKER_TYPE_EXTRACT, + G_PARAM_READWRITE | +- G_PARAM_CONSTRUCT_ONLY)); ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property (object_class, ++ PROP_PERSISTENCE, ++ g_param_spec_object ("persistence", ++ NULL, NULL, ++ TRACKER_TYPE_EXTRACT_PERSISTENCE, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private (object_class, + sizeof (TrackerExtractDecoratorPrivate)); + } + +-static void +-decorator_retry_file (GFile *file, +- gpointer user_data) +-{ +- TrackerExtractDecorator *decorator = user_data; +- TrackerExtractDecoratorPrivate *priv = decorator->priv; +- gchar *path; +- +- path = g_file_get_uri (file); +- g_hash_table_insert (priv->recovery_files, path, g_object_ref (file)); +- tracker_decorator_fs_prepend_file (TRACKER_DECORATOR_FS (decorator), file); +-} +- + static void + decorator_ignore_file (GFile *file, + gpointer user_data) +@@ -612,9 +620,6 @@ tracker_extract_decorator_init (TrackerExtractDecorator *decorator) + TrackerExtractDecoratorPrivate *priv; + + decorator->priv = priv = TRACKER_EXTRACT_DECORATOR_GET_PRIVATE (decorator); +- priv->recovery_files = g_hash_table_new_full (g_str_hash, g_str_equal, +- (GDestroyNotify) g_free, +- (GDestroyNotify) g_object_unref); + } + + static gboolean +@@ -667,9 +672,6 @@ tracker_extract_decorator_initable_init (GInitable *initable, + ret = FALSE; + } + +- priv->persistence = tracker_extract_persistence_initialize (decorator_retry_file, +- decorator_ignore_file, +- decorator); + out: + g_clear_object (&conn); + +@@ -685,6 +687,7 @@ tracker_extract_decorator_initable_iface_init (GInitableIface *iface) + + TrackerDecorator * + tracker_extract_decorator_new (TrackerExtract *extract, ++ TrackerExtractPersistence *persistence, + GCancellable *cancellable, + GError **error) + { +@@ -693,5 +696,6 @@ tracker_extract_decorator_new (TrackerExtract *extract, + "data-source", TRACKER_EXTRACT_DATA_SOURCE, + "class-names", supported_classes, + "extractor", extract, ++ "persistence", persistence, + NULL); + } +diff --git a/src/tracker-extract/tracker-extract-decorator.h b/src/tracker-extract/tracker-extract-decorator.h +index 6d16eeb64..9e9146ca1 100644 +--- a/src/tracker-extract/tracker-extract-decorator.h ++++ b/src/tracker-extract/tracker-extract-decorator.h +@@ -24,6 +24,7 @@ + #include + + #include "tracker-extract.h" ++#include "tracker-extract-persistence.h" + + G_BEGIN_DECLS + +@@ -49,6 +50,7 @@ struct TrackerExtractDecoratorClass { + GType tracker_extract_decorator_get_type (void) G_GNUC_CONST; + + TrackerDecorator * tracker_extract_decorator_new (TrackerExtract *extractor, ++ TrackerExtractPersistence *persistence, + GCancellable *cancellable, + GError **error); + +diff --git a/src/tracker-extract/tracker-extract-persistence.c b/src/tracker-extract/tracker-extract-persistence.c +index 1dc542736..3eff4f34d 100644 +--- a/src/tracker-extract/tracker-extract-persistence.c ++++ b/src/tracker-extract/tracker-extract-persistence.c +@@ -25,7 +25,7 @@ typedef struct _TrackerExtractPersistencePrivate TrackerExtractPersistencePrivat + + struct _TrackerExtractPersistencePrivate + { +- GFile *tmp_dir; ++ int fd; + }; + + G_DEFINE_TYPE_WITH_PRIVATE (TrackerExtractPersistence, tracker_extract_persistence, G_TYPE_OBJECT) +@@ -33,241 +33,102 @@ G_DEFINE_TYPE_WITH_PRIVATE (TrackerExtractPersistence, tracker_extract_persisten + static GQuark n_retries_quark = 0; + + static void +-tracker_extract_persistence_class_init (TrackerExtractPersistenceClass *klass) +-{ +- n_retries_quark = g_quark_from_static_string ("tracker-extract-n-retries-quark"); +-} +- +-static void +-tracker_extract_persistence_init (TrackerExtractPersistence *persistence) ++tracker_extract_persistence_finalize (GObject *object) + { +- TrackerExtractPersistencePrivate *priv; +- gchar *dirname, *tmp_path; +- +- priv = tracker_extract_persistence_get_instance_private (persistence); +- +- dirname = g_strdup_printf ("tracker-extract-files.%d", getuid ()); +- tmp_path = g_build_filename (g_get_tmp_dir (), dirname, NULL); +- g_free (dirname); ++ TrackerExtractPersistence *persistence = ++ TRACKER_EXTRACT_PERSISTENCE (object); ++ TrackerExtractPersistencePrivate *priv = ++ tracker_extract_persistence_get_instance_private (persistence); + +- if (g_mkdir_with_parents (tmp_path, 0700) != 0) { +- g_critical ("The directory %s could not be created, or has the wrong permissions", +- tmp_path); +- g_assert_not_reached (); +- } ++ if (priv->fd > 0) ++ close (priv->fd); + +- priv->tmp_dir = g_file_new_for_path (tmp_path); +- g_free (tmp_path); ++ G_OBJECT_CLASS (tracker_extract_persistence_parent_class)->finalize (object); + } + + static void +-increment_n_retries (GFile *file) ++tracker_extract_persistence_class_init (TrackerExtractPersistenceClass *klass) + { +- guint n_retries; ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); + +- n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); +- g_object_set_qdata (G_OBJECT (file), n_retries_quark, GUINT_TO_POINTER (n_retries + 1)); ++ object_class->finalize = tracker_extract_persistence_finalize; + } + +-static GFile * +-persistence_create_symlink_file (TrackerExtractPersistence *persistence, +- GFile *file) ++static void ++tracker_extract_persistence_init (TrackerExtractPersistence *persistence) + { +- TrackerExtractPersistencePrivate *priv; +- guint n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); +- gchar *link_name, *path, *md5; +- GFile *link_file; +- +- priv = tracker_extract_persistence_get_instance_private (persistence); +- path = g_file_get_path (file); +- md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, path, -1); +- link_name = g_strdup_printf ("%d-%s", n_retries, md5); +- link_file = g_file_get_child (priv->tmp_dir, link_name); +- +- g_free (link_name); +- g_free (path); +- g_free (md5); +- +- return link_file; + } + +-static GFile * +-persistence_symlink_get_file (GFileInfo *info) ++TrackerExtractPersistence * ++tracker_extract_persistence_new (void) + { +- const gchar *symlink_name, *symlink_target; +- gchar *md5, **items; +- GFile *file = NULL; +- guint n_retries; +- +- symlink_name = g_file_info_get_name (info); +- symlink_target = g_file_info_get_symlink_target (info); +- +- if (!g_path_is_absolute (symlink_target)) { +- g_critical ("Symlink paths must be absolute, '%s' points to '%s'", +- symlink_name, symlink_target); +- return NULL; +- } +- +- md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, symlink_target, -1); +- items = g_strsplit (symlink_name, "-", 2); +- n_retries = g_strtod (items[0], NULL); +- +- if (g_strcmp0 (items[1], md5) == 0) { +- file = g_file_new_for_path (symlink_target); +- g_object_set_qdata (G_OBJECT (file), n_retries_quark, +- GUINT_TO_POINTER (n_retries)); +- } else { +- g_critical ("path MD5 for '%s' doesn't match with symlink '%s'", +- symlink_target, symlink_name); +- } +- +- g_strfreev (items); +- g_free (md5); +- +- return file; ++ return g_object_new (TRACKER_TYPE_EXTRACT_PERSISTENCE, ++ NULL); + } + +-static gboolean +-persistence_store_file (TrackerExtractPersistence *persistence, +- GFile *file) ++void ++tracker_extract_persistence_set_fd (TrackerExtractPersistence *persistence, ++ int fd) + { +- GError *error = NULL; +- gboolean success; +- GFile *link_file; +- gchar *path; +- +- increment_n_retries (file); +- path = g_file_get_path (file); +- link_file = persistence_create_symlink_file (persistence, file); +- +- success = g_file_make_symbolic_link (link_file, path, NULL, &error); +- +- if (!success) { +- g_warning ("Could not save '%s' into failsafe persistence store: %s", +- path, error ? error->message : "no error given"); +- g_clear_error (&error); +- } +- +- g_object_unref (link_file); +- g_free (path); ++ TrackerExtractPersistencePrivate *priv = ++ tracker_extract_persistence_get_instance_private (persistence); + +- return success; ++ if (priv->fd > 0) ++ close (priv->fd); ++ priv->fd = fd; + } + +-static gboolean +-persistence_remove_file (TrackerExtractPersistence *persistence, +- GFile *file) ++void ++tracker_extract_persistence_set_file (TrackerExtractPersistence *persistence, ++ GFile *file) + { +- GError *error = NULL; +- GFile *link_file; +- gboolean success; ++ TrackerExtractPersistencePrivate *priv = ++ tracker_extract_persistence_get_instance_private (persistence); ++ g_autofree gchar *path = NULL; ++ int len, written = 0, retval; + +- link_file = persistence_create_symlink_file (persistence, file); +- success = g_file_delete (link_file, NULL, &error); +- +- if (!success) { +- gchar *path = g_file_get_path (file); ++ g_return_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence)); ++ g_return_if_fail (!file || G_IS_FILE (file)); + +- g_warning ("Could not delete '%s' from failsafe persistence store", +- path); +- g_free (path); ++ if (file) { ++ path = g_file_get_path (file); ++ } else { ++ path = g_strdup (""); + } + +- g_object_unref (link_file); +- +- return success; +-} +- +-static void +-persistence_retrieve_files (TrackerExtractPersistence *persistence, +- TrackerFileRecoveryFunc retry_func, +- TrackerFileRecoveryFunc ignore_func, +- gpointer user_data) +-{ +- TrackerExtractPersistencePrivate *priv; +- GFileEnumerator *enumerator; +- GFileInfo *info; +- +- priv = tracker_extract_persistence_get_instance_private (persistence); +- enumerator = g_file_enumerate_children (priv->tmp_dir, +- G_FILE_ATTRIBUTE_STANDARD_NAME "," +- G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, +- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, +- NULL, NULL); +- if (!enumerator) +- return; +- +- while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) { +- GFile *file, *symlink_file; +- guint n_retries; +- +- symlink_file = g_file_enumerator_get_child (enumerator, info); +- file = persistence_symlink_get_file (info); +- +- if (!file) { +- /* If we got here, persistence_symlink_get_file() already emitted a g_critical */ +- g_object_unref (symlink_file); +- g_object_unref (info); +- continue; +- } +- +- /* Delete the symlink, it will get probably added back soon after, +- * and n_retries incremented. +- */ +- g_file_delete (symlink_file, NULL, NULL); +- g_object_unref (symlink_file); +- +- n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); ++ /* Write also the trailing \0 */ ++ len = strlen (path) + 1; + +- /* Trigger retry/ignore func for the symlink target */ +- if (n_retries >= MAX_RETRIES) { +- ignore_func (file, user_data); +- } else { +- retry_func (file, user_data); +- } ++ lseek (priv->fd, 0, SEEK_SET); + +- g_object_unref (file); +- g_object_unref (info); +- } +- +- g_file_enumerator_close (enumerator, NULL, NULL); +- g_object_unref (enumerator); +-} +- +-TrackerExtractPersistence * +-tracker_extract_persistence_initialize (TrackerFileRecoveryFunc retry_func, +- TrackerFileRecoveryFunc ignore_func, +- gpointer user_data) +-{ +- static TrackerExtractPersistence *persistence = NULL; ++ while (TRUE) { ++ retval = write (priv->fd, &path[written], len - written); ++ if (retval < 0) ++ break; + +- if (!persistence) { +- persistence = g_object_new (TRACKER_TYPE_EXTRACT_PERSISTENCE, +- NULL); +- persistence_retrieve_files (persistence, +- retry_func, ignore_func, +- user_data); ++ written += retval; ++ if (written >= len) ++ break; + } +- +- return persistence; + } + +-void +-tracker_extract_persistence_add_file (TrackerExtractPersistence *persistence, +- GFile *file) ++GFile * ++tracker_extract_persistence_get_file (TrackerExtractPersistence *persistence) + { +- g_return_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence)); +- g_return_if_fail (G_IS_FILE (file)); ++ TrackerExtractPersistencePrivate *priv = ++ tracker_extract_persistence_get_instance_private (persistence); ++ gchar buf[2048]; ++ int len; + +- persistence_store_file (persistence, file); +-} ++ g_return_val_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence), NULL); + +-void +-tracker_extract_persistence_remove_file (TrackerExtractPersistence *persistence, +- GFile *file) +-{ +- g_return_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence)); +- g_return_if_fail (G_IS_FILE (file)); ++ lseek (priv->fd, 0, SEEK_SET); ++ len = read (priv->fd, buf, sizeof (buf)); ++ if (len <= 0) ++ return NULL; ++ if (buf[0] == '\0') ++ return NULL; + +- persistence_remove_file (persistence, file); ++ buf[len - 1] = '\0'; ++ return g_file_new_for_path (buf); + } +diff --git a/src/tracker-extract/tracker-extract-persistence.h b/src/tracker-extract/tracker-extract-persistence.h +index d5474af0d..c1d498ef7 100644 +--- a/src/tracker-extract/tracker-extract-persistence.h ++++ b/src/tracker-extract/tracker-extract-persistence.h +@@ -34,9 +34,6 @@ G_BEGIN_DECLS + typedef struct _TrackerExtractPersistence TrackerExtractPersistence; + typedef struct _TrackerExtractPersistenceClass TrackerExtractPersistenceClass; + +-typedef void (* TrackerFileRecoveryFunc) (GFile *file, +- gpointer user_data); +- + struct _TrackerExtractPersistence + { + GObject parent_instance; +@@ -49,15 +46,15 @@ struct _TrackerExtractPersistenceClass + + GType tracker_extract_persistence_get_type (void) G_GNUC_CONST; + +-TrackerExtractPersistence * +- tracker_extract_persistence_initialize (TrackerFileRecoveryFunc retry_func, +- TrackerFileRecoveryFunc ignore_func, +- gpointer user_data); ++TrackerExtractPersistence * tracker_extract_persistence_new (void); ++ ++void tracker_extract_persistence_set_fd (TrackerExtractPersistence *persistence, ++ int fd); ++ ++GFile * tracker_extract_persistence_get_file (TrackerExtractPersistence *persistence); + +-void tracker_extract_persistence_add_file (TrackerExtractPersistence *persistence, +- GFile *file); +-void tracker_extract_persistence_remove_file (TrackerExtractPersistence *persistence, +- GFile *file); ++void tracker_extract_persistence_set_file (TrackerExtractPersistence *persistence, ++ GFile *file); + + G_END_DECLS + +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 92333c62f..01eaf2ed0 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -44,6 +44,7 @@ + #include "tracker-extract.h" + #include "tracker-extract-controller.h" + #include "tracker-extract-decorator.h" ++#include "tracker-extract-persistence.h" + + #ifdef THREAD_ENABLE_TRACE + #warning Main thread traces enabled +@@ -269,6 +270,7 @@ main (int argc, char *argv[]) + GMainLoop *my_main_loop; + GDBusConnection *connection; + TrackerMinerProxy *proxy; ++ TrackerExtractPersistence *persistence; + TrackerDomainOntology *domain_ontology; + gchar *domain_name, *dbus_name; + +@@ -355,7 +357,9 @@ main (int argc, char *argv[]) + + tracker_module_manager_load_modules (); + +- decorator = tracker_extract_decorator_new (extract, NULL, &error); ++ persistence = tracker_extract_persistence_new (); ++ ++ decorator = tracker_extract_decorator_new (extract, persistence, NULL, &error); + + if (error) { + g_critical ("Could not start decorator: %s\n", error->message); +@@ -379,7 +383,7 @@ main (int argc, char *argv[]) + + tracker_locale_sanity_check (); + +- controller = tracker_extract_controller_new (decorator, connection); ++ controller = tracker_extract_controller_new (decorator, connection, persistence); + tracker_miner_start (TRACKER_MINER (decorator)); + + /* Request DBus name */ +@@ -425,6 +429,7 @@ main (int argc, char *argv[]) + g_object_unref (extract); + g_object_unref (decorator); + g_object_unref (controller); ++ g_object_unref (persistence); + g_object_unref (proxy); + g_object_unref (connection); + g_object_unref (domain_ontology); +-- +2.43.0 + + +From 7c0d4d69adbdd096fa40dd96a15b61640db2023d Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 24 Sep 2023 23:27:56 +0200 +Subject: [PATCH 05/22] tracker-extract: Disable GstRegistry forking + +This is going nowhere with the sandbox. Also disable some more +needless GST plugins. +--- + src/tracker-extract/tracker-extract-gstreamer.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/tracker-extract/tracker-extract-gstreamer.c b/src/tracker-extract/tracker-extract-gstreamer.c +index 3546069a6..1305ecfa2 100644 +--- a/src/tracker-extract/tracker-extract-gstreamer.c ++++ b/src/tracker-extract/tracker-extract-gstreamer.c +@@ -1306,12 +1306,16 @@ tracker_extract_module_init (GError **error) + /* Lifted from totem-video-thumbnailer */ + const gchar *blacklisted[] = { + "bcmdec", ++ "camerabin", ++ "fluidsynthmidi", ++ "libcamera", + "vaapi", + "video4linux2" + }; + GstRegistry *registry; + guint i; + ++ gst_registry_fork_set_enabled (FALSE); + gst_init (NULL, NULL); + registry = gst_registry_get (); + +-- +2.43.0 + + +From 49493c1f5c2b5fce76d24d598e1388f474a2c0f0 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 22 Sep 2023 23:26:38 +0200 +Subject: [PATCH 06/22] libtracker-miners-common: Extend seccomp rules + +The plan is to extend the seccomp jail so it affects the full +tracker-extract-3 process. With the changes in the previous +commits we've removed the need for filesystem write access. + +We have some remaining outliers, that we're largely sorting +out with rules to error out softly (instead of through SIGSYS). +The only new allowed syscalls are fstatfs and prlimit64 with a +NULL new_limit struct. +--- + .../tracker-seccomp.c | 21 +++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 71b601740..50cfed4f4 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -97,6 +97,8 @@ tracker_seccomp_init (void) + ALLOW_RULE (statfs64); + ALLOW_RULE (lstat); + ALLOW_RULE (lstat64); ++ ALLOW_RULE (statx); ++ ALLOW_RULE (fstatfs); + ALLOW_RULE (access); + ALLOW_RULE (getdents); + ALLOW_RULE (getdents64); +@@ -163,6 +165,22 @@ tracker_seccomp_init (void) + ALLOW_RULE (getpeername); + ALLOW_RULE (shutdown); + ++ ERROR_RULE (inotify_init1, EINVAL); ++ ERROR_RULE (inotify_init, EINVAL); ++ ++ ERROR_RULE (mkdir, EPERM); ++ ERROR_RULE (rename, EPERM); ++ ERROR_RULE (unlink, EPERM); ++ ERROR_RULE (ioctl, EBADF); ++ ERROR_RULE (bind, EACCES); ++ ERROR_RULE (setsockopt, EBADF); ++ ERROR_RULE (sched_getattr, EPERM); ++ ++ /* Allow prlimit64, only if no new limits are being set */ ++ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(prlimit64), 1, ++ SCMP_CMP(2, SCMP_CMP_EQ, 0)) < 0) ++ goto out; ++ + /* 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) +@@ -170,6 +188,9 @@ tracker_seccomp_init (void) + 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_ERRNO (EACCES), SCMP_SYS(socket), 1, ++ SCMP_CMP(0, SCMP_CMP_EQ, AF_NETLINK)) < 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; +-- +2.43.0 + + +From 78c04b87cbdff97990244166a9e8ae95d35419c7 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 22 Sep 2023 23:14:38 +0200 +Subject: [PATCH 07/22] tracker-extract: Extend seccomp jail to full process + +Currently, our main thread is exempted from the seccomp jail. +This was so we could do some menial tasks (e.g. persistence handling +to recover from runtime errors, or error reports on failed extraction) +without caring much about plugging seccomp holes. + +It may be preferable to extend the seccomp jail to the full process +instead, so do that. Now the only thing happening prior to setting +up the seccomp jail is the setting up of nice/scheduler/ioprio +priorities. Everything else, and every thread spawned afterwards is +covered by seccomp. + +Related: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/277 +--- + src/tracker-extract/tracker-extract.c | 5 ----- + src/tracker-extract/tracker-main.c | 24 ++++++++++++++++-------- + 2 files changed, 16 insertions(+), 13 deletions(-) + +diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c +index cd0511e8f..5eafca7d5 100644 +--- a/src/tracker-extract/tracker-extract.c ++++ b/src/tracker-extract/tracker-extract.c +@@ -30,8 +30,6 @@ + #include + #include + +-#include +- + #include + + #include "tracker-extract.h" +@@ -507,9 +505,6 @@ get_metadata (TrackerExtractTask *task) + static gpointer + single_thread_get_metadata (GAsyncQueue *queue) + { +- if (!tracker_seccomp_init ()) +- g_assert_not_reached (); +- + while (TRUE) { + TrackerExtractTask *task; + +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 01eaf2ed0..5cfe073c0 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -196,9 +196,6 @@ run_standalone (void) + + tracker_locale_sanity_check (); + +- /* This makes sure we don't steal all the system's resources */ +- initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, TRUE); +- + file = g_file_new_for_commandline_arg (filename); + uri = g_file_get_uri (file); + +@@ -258,8 +255,8 @@ on_decorator_finished (TrackerDecorator *decorator, + main_loop); + } + +-int +-main (int argc, char *argv[]) ++static int ++do_main (int argc, char *argv[]) + { + GOptionContext *context; + GError *error = NULL; +@@ -345,9 +342,6 @@ main (int argc, char *argv[]) + return run_standalone (); + } + +- /* This makes sure we don't steal all the system's resources */ +- initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, TRUE); +- + extract = tracker_extract_new (TRUE, force_module); + + if (!extract) { +@@ -438,3 +432,17 @@ main (int argc, char *argv[]) + + return EXIT_SUCCESS; + } ++ ++int ++main (int argc, char *argv[]) ++{ ++ /* This function is untouchable! Add things to do_main() */ ++ ++ /* This makes sure we don't steal all the system's resources */ ++ initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, TRUE); ++ ++ if (!tracker_seccomp_init ()) ++ g_assert_not_reached (); ++ ++ return do_main (argc, argv); ++} +-- +2.43.0 + + +From e6f592da48b332ef41493e28a2c2b3dc888aae8c Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 3 Oct 2023 12:44:42 +0200 +Subject: [PATCH 08/22] libtracker-miners-common: Add custom rules through a + define + +Bring some more consistence between our ALLOW/ERROR_RULE defines, +and the "custom" rules where we check syscall arguments. +--- + .../tracker-seccomp.c | 66 +++++++------------ + 1 file changed, 23 insertions(+), 43 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 50cfed4f4..05eebd57b 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -52,6 +52,13 @@ + goto out; \ + } G_STMT_END + ++#define CUSTOM_RULE(call, action, arg1) G_STMT_START { \ ++ int custom_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ ++ if (custom_rule_syscall_number == __NR_SCMP_ERROR || \ ++ seccomp_rule_add (ctx, action, custom_rule_syscall_number, 1, arg1) < 0) \ ++ goto out; \ ++} G_STMT_END ++ + gboolean + tracker_seccomp_init (void) + { +@@ -177,57 +184,30 @@ tracker_seccomp_init (void) + ERROR_RULE (sched_getattr, EPERM); + + /* Allow prlimit64, only if no new limits are being set */ +- if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(prlimit64), 1, +- SCMP_CMP(2, SCMP_CMP_EQ, 0)) < 0) +- goto out; ++ CUSTOM_RULE (prlimit64, SCMP_ACT_ALLOW, SCMP_CMP(2, SCMP_CMP_EQ, 0)); + + /* 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_ERRNO (EACCES), SCMP_SYS(socket), 1, +- SCMP_CMP(0, SCMP_CMP_EQ, AF_NETLINK)) < 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; ++ CUSTOM_RULE (socket, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)); ++ CUSTOM_RULE (socket, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)); ++ CUSTOM_RULE (socket, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(0, SCMP_CMP_EQ, AF_NETLINK)); ++ ++ CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)); ++ CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)); + + /* 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; ++ CUSTOM_RULE (ioctl, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, 1)); ++ CUSTOM_RULE (ioctl, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, 2)); + + /* 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; ++ CUSTOM_RULE (open, SCMP_ACT_ALLOW, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)); ++ CUSTOM_RULE (open, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)); ++ CUSTOM_RULE (open, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)); ++ ++ CUSTOM_RULE (openat, SCMP_ACT_ALLOW, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)); ++ CUSTOM_RULE (openat, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)); ++ CUSTOM_RULE (openat, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)); + + g_debug ("Loading seccomp rules."); + +-- +2.43.0 + + +From ea33d95f6ecc2e088fc0a77891bc1fa5e77da71e Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 3 Oct 2023 12:47:57 +0200 +Subject: [PATCH 09/22] libtracker-miners-common: Improve "bail out" error + loading seccomp rules + +We are out in the dark if we happen to add syscalls that do not exist on +obscure architectures. Keep track of the rules being added, so we can +provide a more useful error if we fall in this situation. +--- + src/libtracker-miners-common/tracker-seccomp.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 05eebd57b..dae1dc426 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -40,6 +40,7 @@ + + #define ALLOW_RULE(call) G_STMT_START { \ + int allow_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ ++ current_syscall = 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; \ +@@ -47,6 +48,7 @@ + + #define ERROR_RULE(call, error) G_STMT_START { \ + int error_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ ++ current_syscall = 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; \ +@@ -54,6 +56,7 @@ + + #define CUSTOM_RULE(call, action, arg1) G_STMT_START { \ + int custom_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ ++ current_syscall = G_STRINGIFY (call); \ + if (custom_rule_syscall_number == __NR_SCMP_ERROR || \ + seccomp_rule_add (ctx, action, custom_rule_syscall_number, 1, arg1) < 0) \ + goto out; \ +@@ -63,6 +66,7 @@ gboolean + tracker_seccomp_init (void) + { + scmp_filter_ctx ctx; ++ const gchar *current_syscall = NULL; + + ctx = seccomp_init (SCMP_ACT_TRAP); + if (ctx == NULL) +@@ -215,7 +219,7 @@ tracker_seccomp_init (void) + return TRUE; + + out: +- g_critical ("Failed to load seccomp rules."); ++ g_critical ("Failed to load seccomp rule for syscall '%s'", current_syscall); + seccomp_release (ctx); + return FALSE; + } +-- +2.43.0 + + +From f24b4617bccb63da09eba0297d344916df3c2723 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 8 Oct 2023 00:02:30 +0200 +Subject: [PATCH 10/22] libtracker-miners-common: Add more seccomp rules + +Seen on debian/ubuntu on some arches. Make mkdirat error out +the same way than mkdir, and allow name_to_handle_at() as +that should be innocuous. + +Closes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/281 +--- + src/libtracker-miners-common/tracker-seccomp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index dae1dc426..d91175aab 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -175,11 +175,13 @@ tracker_seccomp_init (void) + ALLOW_RULE (getsockname); + ALLOW_RULE (getpeername); + ALLOW_RULE (shutdown); ++ ALLOW_RULE (name_to_handle_at); + + ERROR_RULE (inotify_init1, EINVAL); + ERROR_RULE (inotify_init, EINVAL); + + ERROR_RULE (mkdir, EPERM); ++ ERROR_RULE (mkdirat, EPERM); + ERROR_RULE (rename, EPERM); + ERROR_RULE (unlink, EPERM); + ERROR_RULE (ioctl, EBADF); +-- +2.43.0 + + +From 63b88a31d83e569de2eca56381f5614e2a595867 Mon Sep 17 00:00:00 2001 +From: psykose +Date: Tue, 17 Oct 2023 13:29:56 +0000 +Subject: [PATCH 11/22] libtracker-miners-common: use macro stringify instead + of G_STRINGIFY + +G_STRINGIFY performs macro expansion; this means that on musl, the LFS64 +interface define of + #define getdents64 getdents + +gets expanded to 'getdents', so the getdents64 syscall becomes not +allowed. using the preprocessor #stringify does not expand the name, so +this works as expected. + +closes #285 +--- + src/libtracker-miners-common/tracker-seccomp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index d91175aab..a2dff8296 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -39,24 +39,24 @@ + #include + + #define ALLOW_RULE(call) G_STMT_START { \ +- int allow_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ +- current_syscall = G_STRINGIFY (call); \ ++ int allow_rule_syscall_number = seccomp_syscall_resolve_name (#call); \ ++ current_syscall = #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)); \ +- current_syscall = G_STRINGIFY (call); \ ++ int error_rule_syscall_number = seccomp_syscall_resolve_name (#call); \ ++ current_syscall = #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 + + #define CUSTOM_RULE(call, action, arg1) G_STMT_START { \ +- int custom_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ +- current_syscall = G_STRINGIFY (call); \ ++ int custom_rule_syscall_number = seccomp_syscall_resolve_name (#call); \ ++ current_syscall = #call; \ + if (custom_rule_syscall_number == __NR_SCMP_ERROR || \ + seccomp_rule_add (ctx, action, custom_rule_syscall_number, 1, arg1) < 0) \ + goto out; \ +-- +2.43.0 + + +From 01a0453b86416d6a16592c29b351ace8d12b8d42 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 16 Oct 2023 11:15:21 +0200 +Subject: [PATCH 12/22] libtracker-miners-common: Allow some more syscalls for + i686 + +These are seen on Debian i686 with the default dependencies pulled +from apt-get build-dep tracker-miners. There's mainly 32-bit syscall +variants (getgid32, fstatfs64), some fancy stuff so far unseen in 64-bit +(timerfd_create), and for some unfathomable reason, gstreamer openNI2 +module using chdir() to change the CWD. + +Everything is harmless though, so go with that. + +Closes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/284 +--- + src/libtracker-miners-common/tracker-seccomp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index a2dff8296..0c9054117 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -89,6 +89,8 @@ tracker_seccomp_init (void) + ALLOW_RULE (exit_group); + ALLOW_RULE (getuid); + ALLOW_RULE (getuid32); ++ ALLOW_RULE (getgid); ++ ALLOW_RULE (getgid32); + ALLOW_RULE (getegid); + ALLOW_RULE (getegid32); + ALLOW_RULE (geteuid); +@@ -110,6 +112,7 @@ tracker_seccomp_init (void) + ALLOW_RULE (lstat64); + ALLOW_RULE (statx); + ALLOW_RULE (fstatfs); ++ ALLOW_RULE (fstatfs64); + ALLOW_RULE (access); + ALLOW_RULE (getdents); + ALLOW_RULE (getdents64); +@@ -119,6 +122,7 @@ tracker_seccomp_init (void) + ALLOW_RULE (time); + ALLOW_RULE (fsync); + ALLOW_RULE (umask); ++ ALLOW_RULE (chdir); + /* Processes and threads */ + ALLOW_RULE (clone); + ALLOW_RULE (futex); +@@ -148,6 +152,7 @@ tracker_seccomp_init (void) + ALLOW_RULE (clock_gettime); + ALLOW_RULE (clock_getres); + ALLOW_RULE (gettimeofday); ++ ALLOW_RULE (timerfd_create); + /* Descriptors */ + ALLOW_RULE (close); + ALLOW_RULE (read); +-- +2.43.0 + + +From eeda731c25d7fd7f606bc5c13420d4e848946337 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 12:52:32 +0200 +Subject: [PATCH 13/22] libtracker-miners-common: Allow NETLINK_KOBJECT_UEVENT + access + +Sadly, it remains extremely finicky to provide detailed rules with +differing actions for socket() through libseccomp(), due to the way this +syscall is (was?) wrapped through the multiplexed socketcall() syscall on +some architectures. + +Since we cannot provide different SCMP_ACT_* values, and we cannot let +AF_NETLINK/NETLINK_KOBJECT_UEVENT requests fail with SIGSYS (e.g. +video4linux2 gstreamer plugin wants udev access and will trigger this +right in gst_init()), go with SCMP_ACT_ALLOW for this specific combination, +along with AF_LOCAL. + +This kind of socket is effectively readonly to unprivileged users and +local by definition, so it does not seem a big risk to allow, the only +lingering question being "why should we allow this". + +Closes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/283 +--- + src/libtracker-miners-common/tracker-seccomp.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 0c9054117..cb1ba2f8c 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -36,6 +36,8 @@ + #include + #include + ++#include ++ + #include + + #define ALLOW_RULE(call) G_STMT_START { \ +@@ -62,6 +64,14 @@ + goto out; \ + } G_STMT_END + ++#define CUSTOM_RULE_2ARG(call, action, arg1, arg2) G_STMT_START { \ ++ int custom_rule_syscall_number = seccomp_syscall_resolve_name (#call); \ ++ current_syscall = #call; \ ++ if (custom_rule_syscall_number == __NR_SCMP_ERROR || \ ++ seccomp_rule_add (ctx, action, custom_rule_syscall_number, 2, arg1, arg2) < 0) \ ++ goto out; \ ++} G_STMT_END ++ + gboolean + tracker_seccomp_init (void) + { +@@ -197,10 +207,14 @@ tracker_seccomp_init (void) + /* Allow prlimit64, only if no new limits are being set */ + CUSTOM_RULE (prlimit64, SCMP_ACT_ALLOW, SCMP_CMP(2, SCMP_CMP_EQ, 0)); + +- /* Special requirements for socket/socketpair, only on AF_UNIX/AF_LOCAL */ ++ /* Special requirements for socket/socketpair, only on AF_UNIX/AF_LOCAL, ++ * and AF_NETLINK/NETLINK_KOBJECT_UEVENT for udev. ++ */ + CUSTOM_RULE (socket, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)); + CUSTOM_RULE (socket, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)); +- CUSTOM_RULE (socket, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(0, SCMP_CMP_EQ, AF_NETLINK)); ++ CUSTOM_RULE_2ARG (socket, SCMP_ACT_ALLOW, ++ SCMP_CMP (0, SCMP_CMP_EQ, AF_NETLINK), ++ SCMP_CMP (2, SCMP_CMP_EQ, NETLINK_KOBJECT_UEVENT)); + + CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)); + CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)); +-- +2.43.0 + + +From dd954babb31612b635472a12c32ba98fa4dcbf76 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 09:31:33 +0200 +Subject: [PATCH 14/22] libtracker-miners-common: Allow tgkill on self's + process + +This is the syscall underneath abort(), assert(), etc. Let this +syscall through for the purpose of killing self's process, and +don't hide the actual errors. + +Closes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/287 +--- + src/libtracker-miners-common/tracker-seccomp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index cb1ba2f8c..c7f986768 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -204,6 +204,9 @@ tracker_seccomp_init (void) + ERROR_RULE (setsockopt, EBADF); + ERROR_RULE (sched_getattr, EPERM); + ++ /* Allow tgkill on self, for abort() and friends */ ++ CUSTOM_RULE (tgkill, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, getpid())); ++ + /* Allow prlimit64, only if no new limits are being set */ + CUSTOM_RULE (prlimit64, SCMP_ACT_ALLOW, SCMP_CMP(2, SCMP_CMP_EQ, 0)); + +-- +2.43.0 + + +From aeff5f7125bb437247bad1b5cbc190eb2a9789e0 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 12:48:42 +0200 +Subject: [PATCH 15/22] tracker-extract: Initialize modules also before + commandline extraction + +This allows the gstreamer module to block plugins through the registry +in those paths too. +--- + src/tracker-extract/tracker-main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 5cfe073c0..4be5e8f22 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -337,6 +337,9 @@ do_main (int argc, char *argv[]) + g_free (log_filename); + } + ++ tracker_extract_module_manager_init (); ++ tracker_module_manager_load_modules (); ++ + /* Set conditions when we use stand alone settings */ + if (filename) { + return run_standalone (); +@@ -349,8 +352,6 @@ do_main (int argc, char *argv[]) + return EXIT_FAILURE; + } + +- tracker_module_manager_load_modules (); +- + persistence = tracker_extract_persistence_new (); + + decorator = tracker_extract_decorator_new (extract, persistence, NULL, &error); +-- +2.43.0 + + +From 9767d49b33ad071bfa1d1f1869efb59be13191da Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 13:11:07 +0200 +Subject: [PATCH 16/22] libtracker-miners-common: Allow restart_syscall syscall + +This syscall may happen after SIGCONT if a previous SIGSTOP caught +the process mid-syscall. This is a plausible situation with gdb, and +through coredumpd/abrtd/etc. + +Closes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/288 +--- + src/libtracker-miners-common/tracker-seccomp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index c7f986768..76c19a39e 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -145,6 +145,7 @@ tracker_seccomp_init (void) + ALLOW_RULE (waitid); + ALLOW_RULE (waitpid); + ALLOW_RULE (wait4); ++ ALLOW_RULE (restart_syscall); + /* Main loops */ + ALLOW_RULE (poll); + ALLOW_RULE (ppoll); +-- +2.43.0 + + +From 27943111ba1852fe37c1e6dfedcfebf4eff954e1 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 14:12:33 +0200 +Subject: [PATCH 17/22] libtracker-miners-common: Drop ioctl rules for + stdout/stderr + +These were added in the first instance of the sandbox, I do not +remember what they were for, and they seem largely unnecessary +nowadays. +--- + src/libtracker-miners-common/tracker-seccomp.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 76c19a39e..fe8aa1b84 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -223,10 +223,6 @@ tracker_seccomp_init (void) + CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)); + CUSTOM_RULE (socketpair, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)); + +- /* Special requirements for ioctl, allowed on stdout/stderr */ +- CUSTOM_RULE (ioctl, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, 1)); +- CUSTOM_RULE (ioctl, SCMP_ACT_ALLOW, SCMP_CMP(0, SCMP_CMP_EQ, 2)); +- + /* Special requirements for open/openat, allow O_RDONLY calls, + * but fail if write permissions are requested. + */ +-- +2.43.0 + + +From bf8370b379c75a07001204958062f983cfc23896 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 14:28:29 +0200 +Subject: [PATCH 18/22] libtracker-miners-common: Disallow close/dup2/dup3 on + standard I/O FDs + +As an additional measure, forbid these FDs to be replaced by anything. +--- + src/libtracker-miners-common/tracker-seccomp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index fe8aa1b84..723ac4dd9 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -165,7 +165,9 @@ tracker_seccomp_init (void) + ALLOW_RULE (gettimeofday); + ALLOW_RULE (timerfd_create); + /* Descriptors */ +- ALLOW_RULE (close); ++ CUSTOM_RULE (close, SCMP_ACT_ALLOW, SCMP_CMP (0, SCMP_CMP_GT, STDERR_FILENO)); ++ CUSTOM_RULE (dup2, SCMP_ACT_ALLOW, SCMP_CMP (1, SCMP_CMP_GT, STDERR_FILENO)); ++ CUSTOM_RULE (dup3, SCMP_ACT_ALLOW, SCMP_CMP (1, SCMP_CMP_GT, STDERR_FILENO)); + ALLOW_RULE (read); + ALLOW_RULE (pread64); + ALLOW_RULE (lseek); +@@ -175,8 +177,6 @@ tracker_seccomp_init (void) + 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. +-- +2.43.0 + + +From 49c8c7e79cb7746ad15bc84eddcd8ee14fd32dbf Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 17 Oct 2023 16:10:11 +0200 +Subject: [PATCH 19/22] libtracker-miners-common: Forbid some more + open()/openat() flags + +There are some nasty combinations with O_RDONLY that may already +trigger unintended results, like O_CREAT and O_TRUNC. Avoid any +combination that sounds off with O_RDONLY. +--- + src/libtracker-miners-common/tracker-seccomp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index 723ac4dd9..a853863d7 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -226,11 +226,15 @@ tracker_seccomp_init (void) + /* Special requirements for open/openat, allow O_RDONLY calls, + * but fail if write permissions are requested. + */ +- CUSTOM_RULE (open, SCMP_ACT_ALLOW, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)); ++ CUSTOM_RULE (open, SCMP_ACT_ALLOW, ++ SCMP_CMP (1, SCMP_CMP_MASKED_EQ, ++ O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC | O_EXCL, 0)); + CUSTOM_RULE (open, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)); + CUSTOM_RULE (open, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)); + +- CUSTOM_RULE (openat, SCMP_ACT_ALLOW, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)); ++ CUSTOM_RULE (openat, SCMP_ACT_ALLOW, ++ SCMP_CMP (2, SCMP_CMP_MASKED_EQ, ++ O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC | O_EXCL, 0)); + CUSTOM_RULE (openat, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)); + CUSTOM_RULE (openat, SCMP_ACT_ERRNO (EACCES), SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)); + +-- +2.43.0 + + +From 6be14b13541873b5f490164748287fa6b070e0ec Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 23 Oct 2023 19:17:41 +0200 +Subject: [PATCH 20/22] tracker-miner-fs: Preempt GStreamer registry file + creation + +Initialize gstreamer in tracker-miner-fs, mostly as a means to +ensure the registry file is guaranteed to exist and be up-to-date +when the tracker-extract-3 process gets to start up and require the +use of GStreamer plugins. +--- + src/miners/fs/Makefile.am | 2 ++ + src/miners/fs/meson.build | 7 ++++--- + src/miners/fs/tracker-main.c | 7 +++++++ + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/src/miners/fs/Makefile.am b/src/miners/fs/Makefile.am +index cb812e0b5..526d6b0a2 100644 +--- a/src/miners/fs/Makefile.am ++++ b/src/miners/fs/Makefile.am +@@ -7,6 +7,7 @@ AM_CPPFLAGS = \ + -DSHAREDIR=\""$(datadir)"\" \ + -DLOCALEDIR=\""$(localedir)"\" \ + -DLIBEXEC_PATH=\""$(libexecdir)"\" \ ++ $(GSTREAMER_CFLAGS) \ + $(TRACKER_MINER_FS_CFLAGS) + + libexec_PROGRAMS = tracker-miner-fs +@@ -57,6 +58,7 @@ tracker_miner_fs_LDADD = \ + $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ + $(top_builddir)/src/libtracker-miners-common/libtracker-miners-common.la \ + $(BUILD_LIBS) \ ++ $(GSTREAMER_LIBS) \ + $(TRACKER_MINER_FS_LIBS) + + # DBus services +diff --git a/src/miners/fs/meson.build b/src/miners/fs/meson.build +index c26c0240e..9fdfaa395 100644 +--- a/src/miners/fs/meson.build ++++ b/src/miners/fs/meson.build +@@ -14,9 +14,10 @@ sources = [ + ] + + tracker_miner_fs_deps = [ +- tracker_miner, +- tracker_miners_common_dep, +- tracker_extract_dep ++ tracker_miner, ++ tracker_miners_common_dep, ++ tracker_extract_dep, ++ gstreamer, + ] + + if battery_detection_library_name == 'upower' +diff --git a/src/miners/fs/tracker-main.c b/src/miners/fs/tracker-main.c +index e7e809560..44912ba5d 100644 +--- a/src/miners/fs/tracker-main.c ++++ b/src/miners/fs/tracker-main.c +@@ -31,6 +31,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -682,6 +684,11 @@ main (gint argc, gchar *argv[]) + /* Set timezone info */ + tzset (); + ++ /* Preempt possible registry updates, before tracker-extract-3 deals ++ * with gstreamer plugins. ++ */ ++ gst_init (NULL, NULL); ++ + /* Translators: this messagge will apper immediately after the + * usage string - Usage: COMMAND + */ +-- +2.43.0 + + +From 0be7148c185af8bc258dc2e3eab9db9fdf4f1c18 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 25 Oct 2023 11:21:17 +0200 +Subject: [PATCH 21/22] tracker-extract: Disable GST registry updates in + extractor process + +Force disable the attempt to update the GStreamer registry from the extractor +process, creation of files is softly forbidden by the seccomp sandbox anyway. +This will have the nice side effect of avoiding GStreamer from attempting to +load changed/new modules at gst_init() time (and the crazy shit some of them +do during plugin initialization), while the less nice side effect (the extractor +not finding old/stale plugins, and being unable to use new ones) should have been +largely avoided by the previous commit. +--- + src/tracker-extract/tracker-main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c +index 4be5e8f22..dd1f851d3 100644 +--- a/src/tracker-extract/tracker-main.c ++++ b/src/tracker-extract/tracker-main.c +@@ -271,6 +271,8 @@ do_main (int argc, char *argv[]) + TrackerDomainOntology *domain_ontology; + gchar *domain_name, *dbus_name; + ++ g_setenv ("GST_REGISTRY_UPDATE", "no", TRUE); ++ + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +-- +2.43.0 + + +From 2da4f2d681896c8f631578f5b5cab6bc9eb21e93 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Thu, 7 Dec 2023 14:28:43 +0100 +Subject: [PATCH 22/22] libtracker-common: Allow getresuid/getresgid in seccomp + +--- + src/libtracker-miners-common/tracker-seccomp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/libtracker-miners-common/tracker-seccomp.c b/src/libtracker-miners-common/tracker-seccomp.c +index a853863d7..7d705751f 100644 +--- a/src/libtracker-miners-common/tracker-seccomp.c ++++ b/src/libtracker-miners-common/tracker-seccomp.c +@@ -108,6 +108,8 @@ tracker_seccomp_init (void) + ALLOW_RULE (getppid); + ALLOW_RULE (gettid); + ALLOW_RULE (getpid); ++ ALLOW_RULE (getresuid); ++ ALLOW_RULE (getresgid); + ALLOW_RULE (exit); + ALLOW_RULE (getrusage); + ALLOW_RULE (getrlimit); +-- +2.43.0 + diff --git a/SPECS/tracker-miners.spec b/SPECS/tracker-miners.spec index 102d81f..d0bf958 100644 --- a/SPECS/tracker-miners.spec +++ b/SPECS/tracker-miners.spec @@ -14,7 +14,7 @@ Name: tracker-miners Version: 2.1.5 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tracker miners and metadata extractors # libtracker-extract is LGPLv2+; the miners are a mix of GPLv2+ and LGPLv2+ code @@ -22,6 +22,8 @@ License: GPLv2+ and LGPLv2+ URL: https://wiki.gnome.org/Projects/Tracker Source0: https://download.gnome.org/sources/%{name}/2.1/%{name}-%{version}.tar.xz +Patch1: backport-seccomp-improvements.diff + BuildRequires: giflib-devel BuildRequires: intltool BuildRequires: libjpeg-devel @@ -127,6 +129,10 @@ rm -f %{buildroot}%{_libdir}/tracker-miners-2.0/*.so %changelog +* Tue Dec 05 2023 Carlos Garnacho - 2.1.5-2 +- Backport stricter seccomp jail + Resolves: RHEL-12466 + * Fri Sep 28 2018 Kalev Lember - 2.1.5-1 - Update to 2.1.5