From 316b950becdf4b7b3bd3f443955d890b1abee0db Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Wed, 15 Jan 2025 15:15:51 -0600 Subject: [PATCH] camera: fix permission check in OpenPipeWireRemote 6cd99b04d438b1de9b25c7bd928e541609904db3 changed the logic that the camera portal uses to look up permissions for the AccessCamera method. Applications first call AccessCamera to ensure they have camera permission and to prompt the user if permission is missing, then they call OpenPipeWireRemote, which fails if permission is missing. The permission lookup logic needs to be the same in both places. Currently when running Snapshot launched by GNOME Shell (rather than launched in a terminal), Snapshot passes AccessCamera's permission check, then fails OpenPipeWireRemote's permission check, causing camera access to be denied without allowing the user to grant permission. Also, since the same commit the code uses the XdpAppInfo on a secondary thread. I suspect this is unsafe, and the original code avoided doing so; therefore, let's be careful and move this logic to the main thread so that the secondary thread only receives a copy of the app ID, as before. https://gitlab.gnome.org/GNOME/snapshot/-/issues/267 --- src/camera.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/camera.c b/src/camera.c index 4224a0a7b..9b43b36d8 100644 --- a/src/camera.c +++ b/src/camera.c @@ -78,11 +78,7 @@ query_permission_sync (XdpRequest *request) const char *app_id; gboolean allowed; - if (xdp_app_info_is_host (request->app_info)) - app_id = ""; - else - app_id = (const char *)g_object_get_data (G_OBJECT (request), "app-id"); - + app_id = (const char *)g_object_get_data (G_OBJECT (request), "app-id"); permission = xdp_get_permission_sync (app_id, PERMISSION_TABLE, PERMISSION_DEVICE_CAMERA); if (permission == XDP_PERMISSION_ASK || permission == XDP_PERMISSION_UNSET) { @@ -190,6 +186,16 @@ handle_access_camera_in_thread_func (GTask *task, } } +static const char * +app_id_from_app_info (XdpAppInfo *app_info) +{ + /* Automatically grant camera access to unsandboxed apps. */ + if (xdp_app_info_is_host (app_info)) + return ""; + + return xdp_app_info_get_id (app_info); +} + static gboolean handle_access_camera (XdpDbusCamera *object, GDBusMethodInvocation *invocation, @@ -211,9 +217,7 @@ handle_access_camera (XdpDbusCamera *object, REQUEST_AUTOLOCK (request); - app_id = xdp_app_info_get_id (request->app_info); - - + app_id = app_id_from_app_info (request->app_info); g_object_set_data_full (G_OBJECT (request), "app-id", g_strdup (app_id), g_free); xdp_request_export (request, g_dbus_method_invocation_get_connection (invocation)); @@ -288,7 +292,7 @@ handle_open_pipewire_remote (XdpDbusCamera *object, } app_info = xdp_invocation_lookup_app_info_sync (invocation, NULL, &error); - app_id = xdp_app_info_get_id (app_info); + app_id = app_id_from_app_info (app_info); permission = xdp_get_permission_sync (app_id, PERMISSION_TABLE, PERMISSION_DEVICE_CAMERA); if (permission != XDP_PERMISSION_YES) {