From c368da09de9baa8908bb9236404bf77a1933b379 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 19 May 2019 22:36:20 -0700 Subject: [PATCH] libsysprof-ui: allow restricting remote proxy --- src/helpers.c | 145 +++++++++++++++++++++++++ src/helpers.h | 43 ++++---- src/libsysprof/sysprof-helpers.c | 7 ++ src/libsysprof/sysprof-helpers.h | 1 + src/libsysprof/sysprof-process-model.c | 15 ++- src/libsysprof/sysprof-process-model.h | 3 + src/sysprofd/ipc-service-impl.c | 138 +---------------------- src/tests/test-model-filter.c | 1 + src/tests/test-process-model.c | 1 + 9 files changed, 196 insertions(+), 158 deletions(-) diff --git a/src/helpers.c b/src/helpers.c index 603ee99d..3673df3a 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -404,3 +404,148 @@ helpers_list_processes_finish (GAsyncResult *result, return FALSE; } + +static gboolean +needs_escape (const gchar *str) +{ + for (; *str; str++) + { + if (g_ascii_isspace (*str) || *str == '\'' || *str == '"') + return TRUE; + } + + return FALSE; +} + +static void +postprocess_cmdline (gchar **str, + gsize len) +{ + g_autoptr(GPtrArray) parts = g_ptr_array_new_with_free_func (g_free); + g_autofree gchar *instr = NULL; + const gchar *begin = NULL; + + if (len == 0) + return; + + instr = *str; + + for (gsize i = 0; i < len; i++) + { + if (!begin && instr[i]) + { + begin = &instr[i]; + } + else if (begin && instr[i] == '\0') + { + if (needs_escape (begin)) + g_ptr_array_add (parts, g_shell_quote (begin)); + else + g_ptr_array_add (parts, g_strdup (begin)); + + begin = NULL; + } + } + + /* If the last byte was not \0, as can happen with prctl(), then we need + * to add it here manually. + */ + if (begin) + { + if (needs_escape (begin)) + g_ptr_array_add (parts, g_shell_quote (begin)); + else + g_ptr_array_add (parts, g_strdup (begin)); + } + + g_ptr_array_add (parts, NULL); + + *str = g_strjoinv (" ", (gchar **)parts->pdata); +} + +static void +postprocess_rstrip (gchar **str, + gsize len) +{ + g_strchomp (*str); +} + +static void +add_pid_proc_file_to (gint pid, + const gchar *name, + GVariantDict *dict, + void (*postprocess) (gchar **, gsize)) +{ + g_autofree gchar *path = NULL; + g_autofree gchar *contents = NULL; + gsize len; + + g_assert (pid > -1); + g_assert (name != NULL); + g_assert (dict != NULL); + + path = g_strdup_printf ("/proc/%d/%s", pid, name); + + if (g_file_get_contents (path, &contents, &len, NULL)) + { + if (postprocess) + postprocess (&contents, len); + g_variant_dict_insert (dict, name, "s", contents); + } +} + + +GVariant * +helpers_get_process_info (const gchar *attributes) +{ + GVariantBuilder builder; + g_autofree gint *processes = NULL; + gsize n_processes = 0; + gboolean want_statm; + gboolean want_cmdline; + gboolean want_comm; + gboolean want_maps; + gboolean want_mountinfo; + + if (attributes == NULL) + attributes = ""; + + want_statm = !!strstr (attributes, "statm"); + want_cmdline = !!strstr (attributes, "cmdline"); + want_maps = !!strstr (attributes, "maps"); + want_mountinfo = !!strstr (attributes, "mountinfo"); + want_comm = !!strstr (attributes, "comm"); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); + + if (helpers_list_processes (&processes, &n_processes)) + { + for (guint i = 0; i < n_processes; i++) + { + gint pid = processes[i]; + GVariantDict dict; + + g_variant_dict_init (&dict, NULL); + g_variant_dict_insert (&dict, "pid", "i", pid, NULL); + + if (want_statm) + add_pid_proc_file_to (pid, "statm", &dict, postprocess_rstrip); + + if (want_cmdline) + add_pid_proc_file_to (pid, "cmdline", &dict, postprocess_cmdline); + + if (want_comm) + add_pid_proc_file_to (pid, "comm", &dict, postprocess_rstrip); + + if (want_maps) + add_pid_proc_file_to (pid, "maps", &dict, postprocess_rstrip); + + if (want_mountinfo) + add_pid_proc_file_to (pid, "mountinfo", &dict, postprocess_rstrip); + + g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); + } + } + + return g_variant_take_ref (g_variant_builder_end (&builder)); +} diff --git a/src/helpers.h b/src/helpers.h index 0aa0470d..faaae31e 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -27,26 +27,27 @@ G_BEGIN_DECLS -gboolean helpers_can_see_pids (void); -gboolean helpers_list_processes (gint32 **processes, - gsize *n_processes); -void helpers_list_processes_async (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean helpers_list_processes_finish (GAsyncResult *result, - gint32 **processes, - gsize *n_processes, - GError **error); -gboolean helpers_perf_event_open (GVariant *options, - gint32 pid, - gint32 cpu, - gint group_fd, - guint64 flags, - gint *out_fd); -gboolean helpers_get_proc_file (const gchar *path, - gchar **contents, - gsize *len); -gboolean helpers_get_proc_fd (const gchar *path, - gint *out_fd); +gboolean helpers_can_see_pids (void); +gboolean helpers_list_processes (gint32 **processes, + gsize *n_processes); +void helpers_list_processes_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean helpers_list_processes_finish (GAsyncResult *result, + gint32 **processes, + gsize *n_processes, + GError **error); +gboolean helpers_perf_event_open (GVariant *options, + gint32 pid, + gint32 cpu, + gint group_fd, + guint64 flags, + gint *out_fd); +gboolean helpers_get_proc_file (const gchar *path, + gchar **contents, + gsize *len); +gboolean helpers_get_proc_fd (const gchar *path, + gint *out_fd); +GVariant *helpers_get_process_info (const gchar *attributes); G_END_DECLS diff --git a/src/libsysprof/sysprof-helpers.c b/src/libsysprof/sysprof-helpers.c index 06512a8d..b8e60db6 100644 --- a/src/libsysprof/sysprof-helpers.c +++ b/src/libsysprof/sysprof-helpers.c @@ -627,6 +627,7 @@ sysprof_helpers_authorize_finish (SysprofHelpers *self, gboolean sysprof_helpers_get_process_info (SysprofHelpers *self, const gchar *attributes, + gboolean no_proxy, GCancellable *cancellable, GVariant **info, GError **error) @@ -636,6 +637,12 @@ sysprof_helpers_get_process_info (SysprofHelpers *self, g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); g_assert (info != NULL); + if (no_proxy) + { + *info = helpers_get_process_info (attributes); + return TRUE; + } + return ipc_service_call_get_process_info_sync (self->proxy, attributes, info, cancellable, error); } diff --git a/src/libsysprof/sysprof-helpers.h b/src/libsysprof/sysprof-helpers.h index 99aae855..3cce84af 100644 --- a/src/libsysprof/sysprof-helpers.h +++ b/src/libsysprof/sysprof-helpers.h @@ -75,6 +75,7 @@ gboolean sysprof_helpers_get_proc_file_finish (SysprofHelpers GError **error); gboolean sysprof_helpers_get_process_info (SysprofHelpers *self, const gchar *attributes, + gboolean no_proxy, GCancellable *cancellable, GVariant **info, GError **error); diff --git a/src/libsysprof/sysprof-process-model.c b/src/libsysprof/sysprof-process-model.c index 93e07555..ec7e676d 100644 --- a/src/libsysprof/sysprof-process-model.c +++ b/src/libsysprof/sysprof-process-model.c @@ -32,8 +32,9 @@ struct _SysprofProcessModel { GObject parent_instance; - guint reload_source; GPtrArray *items; + guint reload_source; + guint no_proxy : 1; }; static void list_model_iface_init (GListModelInterface *iface); @@ -181,6 +182,7 @@ sysprof_process_model_reload_worker (GTask *task, gpointer task_data, GCancellable *cancellable) { + SysprofProcessModel *self = source_object; SysprofHelpers *helpers = sysprof_helpers_get_default (); g_autoptr(GPtrArray) ret = NULL; g_autoptr(GVariant) info = NULL; @@ -190,7 +192,7 @@ sysprof_process_model_reload_worker (GTask *task, ret = g_ptr_array_new_with_free_func (g_object_unref); - if (sysprof_helpers_get_process_info (helpers, "pid,cmdline,comm", NULL, &info, NULL)) + if (sysprof_helpers_get_process_info (helpers, "pid,cmdline,comm", self->no_proxy, NULL, &info, NULL)) { gsize n_children = g_variant_n_children (info); @@ -294,3 +296,12 @@ list_model_iface_init (GListModelInterface *iface) iface->get_n_items = sysprof_process_model_get_n_items; iface->get_item = sysprof_process_model_get_item; } + +void +sysprof_process_model_set_no_proxy (SysprofProcessModel *self, + gboolean no_proxy) +{ + g_return_if_fail (SYSPROF_IS_PROCESS_MODEL (self)); + + self->no_proxy = !!no_proxy; +} diff --git a/src/libsysprof/sysprof-process-model.h b/src/libsysprof/sysprof-process-model.h index 2084e601..9737b774 100644 --- a/src/libsysprof/sysprof-process-model.h +++ b/src/libsysprof/sysprof-process-model.h @@ -38,6 +38,9 @@ G_DECLARE_FINAL_TYPE (SysprofProcessModel, sysprof_process_model, SYSPROF, PROCE SYSPROF_AVAILABLE_IN_ALL SysprofProcessModel *sysprof_process_model_new (void); SYSPROF_AVAILABLE_IN_ALL +void sysprof_process_model_set_no_proxy (SysprofProcessModel *self, + gboolean no_proxy); +SYSPROF_AVAILABLE_IN_ALL void sysprof_process_model_reload (SysprofProcessModel *self); SYSPROF_AVAILABLE_IN_ALL void sysprof_process_model_queue_reload (SysprofProcessModel *self); diff --git a/src/sysprofd/ipc-service-impl.c b/src/sysprofd/ipc-service-impl.c index c2d8ed29..0da8acd3 100644 --- a/src/sysprofd/ipc-service-impl.c +++ b/src/sysprofd/ipc-service-impl.c @@ -237,151 +237,19 @@ ipc_service_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton, return ret; } -static gboolean -needs_escape (const gchar *str) -{ - for (; *str; str++) - { - if (g_ascii_isspace (*str) || *str == '\'' || *str == '"') - return TRUE; - } - - return FALSE; -} - -static void -postprocess_cmdline (gchar **str, - gsize len) -{ - g_autoptr(GPtrArray) parts = g_ptr_array_new_with_free_func (g_free); - g_autofree gchar *instr = NULL; - const gchar *begin = NULL; - - if (len == 0) - return; - - instr = *str; - - for (gsize i = 0; i < len; i++) - { - if (!begin && instr[i]) - { - begin = &instr[i]; - } - else if (begin && instr[i] == '\0') - { - if (needs_escape (begin)) - g_ptr_array_add (parts, g_shell_quote (begin)); - else - g_ptr_array_add (parts, g_strdup (begin)); - - begin = NULL; - } - } - - /* If the last byte was not \0, as can happen with prctl(), then we need - * to add it here manually. - */ - if (begin) - { - if (needs_escape (begin)) - g_ptr_array_add (parts, g_shell_quote (begin)); - else - g_ptr_array_add (parts, g_strdup (begin)); - } - - g_ptr_array_add (parts, NULL); - - *str = g_strjoinv (" ", (gchar **)parts->pdata); -} - -static void -postprocess_rstrip (gchar **str, - gsize len) -{ - g_strchomp (*str); -} - -static void -add_pid_proc_file_to (gint pid, - const gchar *name, - GVariantDict *dict, - void (*postprocess) (gchar **, gsize)) -{ - g_autofree gchar *path = NULL; - g_autofree gchar *contents = NULL; - gsize len; - - g_assert (pid > -1); - g_assert (name != NULL); - g_assert (dict != NULL); - - path = g_strdup_printf ("/proc/%d/%s", pid, name); - - if (g_file_get_contents (path, &contents, &len, NULL)) - { - if (postprocess) - postprocess (&contents, len); - g_variant_dict_insert (dict, name, "s", contents); - } -} - static gboolean ipc_service_impl_handle_get_process_info (IpcService *service, GDBusMethodInvocation *invocation, const gchar *attributes) { - GVariantBuilder builder; - g_autofree gint *processes = NULL; - gsize n_processes = 0; - gboolean want_statm; - gboolean want_cmdline; - gboolean want_comm; - gboolean want_maps; - gboolean want_mountinfo; + g_autoptr(GVariant) res = NULL; g_assert (IPC_IS_SERVICE (service)); g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_assert (attributes != NULL); - want_statm = !!strstr (attributes, "statm"); - want_cmdline = !!strstr (attributes, "cmdline"); - want_maps = !!strstr (attributes, "maps"); - want_mountinfo = !!strstr (attributes, "mountinfo"); - want_comm = !!strstr (attributes, "comm"); - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); - - if (helpers_list_processes (&processes, &n_processes)) - { - for (guint i = 0; i < n_processes; i++) - { - gint pid = processes[i]; - GVariantDict dict; - - g_variant_dict_init (&dict, NULL); - g_variant_dict_insert (&dict, "pid", "i", pid, NULL); - - if (want_statm) - add_pid_proc_file_to (pid, "statm", &dict, postprocess_rstrip); - - if (want_cmdline) - add_pid_proc_file_to (pid, "cmdline", &dict, postprocess_cmdline); - - if (want_comm) - add_pid_proc_file_to (pid, "comm", &dict, postprocess_rstrip); - - if (want_maps) - add_pid_proc_file_to (pid, "maps", &dict, postprocess_rstrip); - - if (want_mountinfo) - add_pid_proc_file_to (pid, "mountinfo", &dict, postprocess_rstrip); - - g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); - } - } - - ipc_service_complete_get_process_info (service, invocation, g_variant_builder_end (&builder)); + res = helpers_get_process_info (attributes); + ipc_service_complete_get_process_info (service, invocation, res); return TRUE; } diff --git a/src/tests/test-model-filter.c b/src/tests/test-model-filter.c index 4c2d0a5b..fb856a6f 100644 --- a/src/tests/test-model-filter.c +++ b/src/tests/test-model-filter.c @@ -143,6 +143,7 @@ test_process (void) filter = sysprof_model_filter_new (G_LIST_MODEL (model)); + sysprof_process_model_set_no_proxy (model, TRUE); sysprof_process_model_reload (model); for (guint i = 0; i < G_N_ELEMENTS (searches); i++) diff --git a/src/tests/test-process-model.c b/src/tests/test-process-model.c index ca42e568..42e347cf 100644 --- a/src/tests/test-process-model.c +++ b/src/tests/test-process-model.c @@ -78,6 +78,7 @@ main (gint argc, gtk_container_add (GTK_CONTAINER (scroller), list); model = sysprof_process_model_new (); + sysprof_process_model_set_no_proxy (model, TRUE); filter = sysprof_model_filter_new (G_LIST_MODEL (model)); gtk_list_box_bind_model (GTK_LIST_BOX (list), G_LIST_MODEL (filter), create_row, NULL, NULL);