diff --git a/src/libsysprof/sysprof-profiler.c b/src/libsysprof/sysprof-profiler.c index ab3c133e..0017adb5 100644 --- a/src/libsysprof/sysprof-profiler.c +++ b/src/libsysprof/sysprof-profiler.c @@ -33,10 +33,12 @@ struct _SysprofProfiler GObject parent_instance; GPtrArray *instruments; SysprofSpawnable *spawnable; + guint acquire_privileges : 1; }; enum { PROP_0, + PROP_ACQUIRE_PRIVILEGES, PROP_SPAWNABLE, N_PROPS }; @@ -66,6 +68,10 @@ sysprof_profiler_get_property (GObject *object, switch (prop_id) { + case PROP_ACQUIRE_PRIVILEGES: + g_value_set_boolean (value, sysprof_profiler_get_acquire_privileges (self)); + break; + case PROP_SPAWNABLE: g_value_set_object (value, sysprof_profiler_get_spawnable (self)); break; @@ -85,6 +91,10 @@ sysprof_profiler_set_property (GObject *object, switch (prop_id) { + case PROP_ACQUIRE_PRIVILEGES: + sysprof_profiler_set_acquire_privileges (self, g_value_get_boolean (value)); + break; + case PROP_SPAWNABLE: sysprof_profiler_set_spawnable (self, g_value_get_object (value)); break; @@ -103,6 +113,13 @@ sysprof_profiler_class_init (SysprofProfilerClass *klass) object_class->get_property = sysprof_profiler_get_property; object_class->set_property = sysprof_profiler_set_property; + properties[PROP_ACQUIRE_PRIVILEGES] = + g_param_spec_boolean ("acquire-privileges", NULL, NULL, + TRUE, + (G_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_STATIC_STRINGS)); + properties [PROP_SPAWNABLE] = g_param_spec_object ("spawnable", NULL, NULL, SYSPROF_TYPE_SPAWNABLE, @@ -114,6 +131,7 @@ sysprof_profiler_class_init (SysprofProfilerClass *klass) static void sysprof_profiler_init (SysprofProfiler *self) { + self->acquire_privileges = TRUE; self->instruments = g_ptr_array_new_with_free_func (g_object_unref); #ifdef __linux__ @@ -169,7 +187,8 @@ sysprof_profiler_record_async (SysprofProfiler *self, recording = _sysprof_recording_new (writer, self->spawnable, (SysprofInstrument **)self->instruments->pdata, - self->instruments->len); + self->instruments->len, + self->acquire_privileges); g_task_return_pointer (task, g_object_ref (recording), g_object_unref); @@ -225,3 +244,36 @@ sysprof_profiler_set_spawnable (SysprofProfiler *self, if (g_set_object (&self->spawnable, spawnable)) g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPAWNABLE]); } + +gboolean +sysprof_profiler_get_acquire_privileges (SysprofProfiler *self) +{ + g_return_val_if_fail (SYSPROF_IS_PROFILER (self), FALSE); + + return self->acquire_privileges; +} + +/** + * sysprof_profiler_set_acquire_privileges: + * @self: a [class@Sysprof.Profiler] + * + * Sets if the the profiler should automatically acquire privileges using + * D-Bus, Policy-Kit, and sysprofd. + * + * Set to false if you want to profile only from what the current process + * can see. Generally that means your user needs perf capabilities. + */ +void +sysprof_profiler_set_acquire_privileges (SysprofProfiler *self, + gboolean acquire_privileges) +{ + g_return_if_fail (SYSPROF_IS_PROFILER (self)); + + acquire_privileges = !!acquire_privileges; + + if (self->acquire_privileges != acquire_privileges) + { + self->acquire_privileges = acquire_privileges; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACQUIRE_PRIVILEGES]); + } +} diff --git a/src/libsysprof/sysprof-profiler.h b/src/libsysprof/sysprof-profiler.h index 42fec019..9b5ac45a 100644 --- a/src/libsysprof/sysprof-profiler.h +++ b/src/libsysprof/sysprof-profiler.h @@ -36,24 +36,29 @@ SYSPROF_AVAILABLE_IN_ALL G_DECLARE_FINAL_TYPE (SysprofProfiler, sysprof_profiler, SYSPROF, PROFILER, GObject) SYSPROF_AVAILABLE_IN_ALL -SysprofProfiler *sysprof_profiler_new (void); +SysprofProfiler *sysprof_profiler_new (void); SYSPROF_AVAILABLE_IN_ALL -SysprofSpawnable *sysprof_profiler_get_spawnable (SysprofProfiler *self); +SysprofSpawnable *sysprof_profiler_get_spawnable (SysprofProfiler *self); SYSPROF_AVAILABLE_IN_ALL -void sysprof_profiler_set_spawnable (SysprofProfiler *self, - SysprofSpawnable *spawnable); +void sysprof_profiler_set_spawnable (SysprofProfiler *self, + SysprofSpawnable *spawnable); SYSPROF_AVAILABLE_IN_ALL -void sysprof_profiler_add_instrument (SysprofProfiler *self, - SysprofInstrument *instrument); +void sysprof_profiler_add_instrument (SysprofProfiler *self, + SysprofInstrument *instrument); SYSPROF_AVAILABLE_IN_ALL -void sysprof_profiler_record_async (SysprofProfiler *self, - SysprofCaptureWriter *writer, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +void sysprof_profiler_record_async (SysprofProfiler *self, + SysprofCaptureWriter *writer, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); SYSPROF_AVAILABLE_IN_ALL -SysprofRecording *sysprof_profiler_record_finish (SysprofProfiler *self, - GAsyncResult *result, - GError **error); +SysprofRecording *sysprof_profiler_record_finish (SysprofProfiler *self, + GAsyncResult *result, + GError **error); +SYSPROF_AVAILABLE_IN_49 +gboolean sysprof_profiler_get_acquire_privileges (SysprofProfiler *self); +SYSPROF_AVAILABLE_IN_49 +void sysprof_profiler_set_acquire_privileges (SysprofProfiler *self, + gboolean acquire_privileges); G_END_DECLS diff --git a/src/libsysprof/sysprof-recording-private.h b/src/libsysprof/sysprof-recording-private.h index 15fb7f16..3d67b6b2 100644 --- a/src/libsysprof/sysprof-recording-private.h +++ b/src/libsysprof/sysprof-recording-private.h @@ -79,12 +79,18 @@ struct _SysprofRecording /* The process we have spawned, if any */ GSubprocess *subprocess; + + /* If we should preauth or otherwise use sysprofd to access + * privileges when setting up the recording. + */ + guint use_sysprofd : 1; }; SysprofRecording *_sysprof_recording_new (SysprofCaptureWriter *writer, SysprofSpawnable *spawnable, SysprofInstrument **instruments, - guint n_instruments); + guint n_instruments, + gboolean use_sysprofd); void _sysprof_recording_start (SysprofRecording *self); SysprofSpawnable *_sysprof_recording_get_spawnable (SysprofRecording *self); DexFuture *_sysprof_recording_add_file (SysprofRecording *self, diff --git a/src/libsysprof/sysprof-recording.c b/src/libsysprof/sysprof-recording.c index 57e53e7e..bb7580d2 100644 --- a/src/libsysprof/sysprof-recording.c +++ b/src/libsysprof/sysprof-recording.c @@ -27,6 +27,7 @@ #include #include "sysprof-recording-private.h" +#include "sysprof-util-private.h" enum { PROP_0, @@ -99,6 +100,7 @@ static DexFuture * sysprof_recording_fiber (gpointer user_data) { SysprofRecording *self = user_data; + g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GCancellable) cancellable = NULL; g_autoptr(DexFuture) record = NULL; g_autoptr(DexFuture) monitor = NULL; @@ -115,12 +117,24 @@ sysprof_recording_fiber (gpointer user_data) cancellable = g_cancellable_new (); - /* First ensure that all our required policy have been acquired on - * the bus so that we don't need to individually acquire them from - * each of the instruments after the recording starts. - */ - if (!dex_await (_sysprof_instruments_acquire_policy (self->instruments, self), &error)) - return dex_future_new_for_error (g_steal_pointer (&error)); + if (self->use_sysprofd) + { + /* Get our D-Bus system connection if we're using sysprofd. */ + if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), NULL))) + return dex_future_new_for_error (g_steal_pointer (&error)); + + /* Let every instrument know what bus we're using so that they can + * automatically enable/disable sysprofd/policy-kit integration. + */ + _sysprof_instruments_set_connection (self->instruments, connection); + + /* First ensure that all our required policy have been acquired on + * the bus so that we don't need to individually acquire them from + * each of the instruments after the recording starts. + */ + if (!dex_await (_sysprof_instruments_acquire_policy (self->instruments, self), &error)) + return dex_future_new_for_error (g_steal_pointer (&error)); + } /* Now allow instruments to prepare for the recording */ if (!dex_await (_sysprof_instruments_prepare (self->instruments, self), &error)) @@ -420,7 +434,8 @@ SysprofRecording * _sysprof_recording_new (SysprofCaptureWriter *writer, SysprofSpawnable *spawnable, SysprofInstrument **instruments, - guint n_instruments) + guint n_instruments, + gboolean use_sysprofd) { SysprofRecording *self; @@ -428,6 +443,7 @@ _sysprof_recording_new (SysprofCaptureWriter *writer, self = g_object_new (SYSPROF_TYPE_RECORDING, NULL); self->writer = sysprof_capture_writer_ref (writer); + self->use_sysprofd = !!use_sysprofd; g_set_object (&self->spawnable, spawnable); @@ -517,6 +533,7 @@ typedef struct _AddFile SysprofCaptureWriter *writer; char *path; guint compress : 1; + guint use_sysprofd : 1; } AddFile; static void @@ -572,25 +589,18 @@ sysprof_recording_add_file_fiber (gpointer user_data) if (g_file_has_prefix (file, proc)) { g_autoptr(GDBusConnection) connection = NULL; - g_autoptr(GVariant) reply = NULL; g_autoptr(GBytes) input_bytes = NULL; - if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error))) + if (add_file->use_sysprofd) + { + /* Only use D-Bus if sysprofd use is requested */ + if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error))) + return dex_future_new_for_error (g_steal_pointer (&error)); + } + + if (!(input_bytes = dex_await_boxed (sysprof_get_proc_file_bytes (connection, g_file_get_path (file)), &error))) return dex_future_new_for_error (g_steal_pointer (&error)); - if (!(reply = dex_await_variant (dex_dbus_connection_call (connection, - "org.gnome.Sysprof3", - "/org/gnome/Sysprof3", - "org.gnome.Sysprof3.Service", - "GetProcFile", - g_variant_new ("(^ay)", g_file_get_path (file)), - G_VARIANT_TYPE ("(ay)"), - G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION, - G_MAXINT), - &error))) - return dex_future_new_for_error (g_steal_pointer (&error)); - - input_bytes = g_variant_get_data_as_bytes (reply); input = g_memory_input_stream_new_from_bytes (input_bytes); } else @@ -662,6 +672,7 @@ _sysprof_recording_add_file (SysprofRecording *self, add_file->writer = sysprof_capture_writer_ref (self->writer); add_file->path = g_strdup (path); add_file->compress = !!compress; + add_file->use_sysprofd = self->use_sysprofd; return dex_scheduler_spawn (NULL, 0, sysprof_recording_add_file_fiber,