summaryrefslogtreecommitdiff
path: root/src/gclue-client-info.c
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2017-03-28 14:50:17 +0200
committerBastien Nocera <hadess@hadess.net>2018-05-02 17:04:59 +0200
commita5afe7a0ee971371423edaca4fdd43b9b7b05a1e (patch)
tree958dbb100b80c28abf319c21350a504041a9dbc5 /src/gclue-client-info.c
parentc26ecf714c4711ca92bec892b305c7de842ffade (diff)
downloadgeoclue-a5afe7a0ee971371423edaca4fdd43b9b7b05a1e.tar.gz
client-info: Replace desktop ID detection for new Flatpak
For newer (>= 0.6.10) versions of Flatpak, the way to export the desktop ID has changed from requiring cgroups to not requiring it. See https://github.com/flatpak/flatpak/releases/tag/0.6.10 This changes the private gclue_client_info_get_xdg_id() API to return a NULL xdg_id should the code fail to read the Flatpak ID for a Flatpak'ed application, and consider it to be disqualifying: " Like parse_app_info_from_fileinfo(), returns NULL on failure, "" (an empty string) if not sandboxed, and a desktop ID otherwise " https://bugs.freedesktop.org/show_bug.cgi?id=97776
Diffstat (limited to 'src/gclue-client-info.c')
-rw-r--r--src/gclue-client-info.c121
1 files changed, 80 insertions, 41 deletions
diff --git a/src/gclue-client-info.c b/src/gclue-client-info.c
index 64057c0..5b1108e 100644
--- a/src/gclue-client-info.c
+++ b/src/gclue-client-info.c
@@ -21,6 +21,10 @@
*/
#include <glib/gi18n.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
#include "gclue-client-info.h"
@@ -181,52 +185,85 @@ on_name_vanished (GDBusConnection *connection,
0);
}
-/* Based on got_credentials_cb() from xdg-app source code */
-static char *
-get_xdg_id (guint32 pid)
+/* Based on xdp_get_app_id_from_pid() from xdg-desktop-portal
+ * Returns NULL on failure, keyfile with name "" if not sandboxed, and full app-info otherwise */
+static GKeyFile *
+parse_app_info_from_fileinfo (int pid)
{
- char *xdg_id = NULL;
- g_autofree char *path = NULL;
- g_autofree char *content = NULL;
- gchar **lines;
- int i;
-
- path = g_strdup_printf ("/proc/%u/cgroup", pid);
-
- if (!g_file_get_contents (path, &content, NULL, NULL))
- return NULL;
- lines = g_strsplit (content, "\n", -1);
-
- for (i = 0; lines[i] != NULL; i++) {
- const char *unit = lines[i] + strlen ("1:name=systemd:");
- g_autofree char *scope = NULL;
- const char *name;
- char *dash;
-
- if (!g_str_has_prefix (lines[i], "1:name=systemd:"))
- continue;
-
- scope = g_path_get_basename (unit);
- if ((!g_str_has_prefix (scope, "xdg-app-") &&
- !g_str_has_prefix (scope, "flatpak-")) ||
- !g_str_has_suffix (scope, ".scope"))
- break;
-
- /* strlen("flatpak-") == strlen("xdg-app-")
- * so all is good here */
- name = scope + strlen("xdg-app-");
- dash = strchr (name, '-');
+ g_autofree char *root_path = NULL;
+ g_autofree char *path = NULL;
+ g_autofree char *content = NULL;
+ g_autofree char *app_id = NULL;
+ int root_fd = -1;
+ int info_fd = -1;
+ struct stat stat_buf;
+ g_autoptr(GError) local_error = NULL;
+ g_autoptr(GMappedFile) mapped = NULL;
+ g_autoptr(GKeyFile) metadata = NULL;
+
+ root_path = g_strdup_printf ("/proc/%u/root", pid);
+ root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
+ if (root_fd == -1)
+ {
+ /* Not able to open the root dir shouldn't happen. Probably the app died and
+ we're failing due to /proc/$pid not existing. In that case fail instead
+ of treating this as privileged. */
+ return NULL;
+ }
+
+ metadata = g_key_file_new ();
+
+ info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ close (root_fd);
+ if (info_fd == -1)
+ {
+ if (errno == ENOENT)
+ {
+ /* No file => on the host */
+ g_key_file_set_string (metadata, "Application", "name", "");
+ return g_steal_pointer (&metadata);
+ }
- if (dash == NULL)
- break;
+ /* Some weird error => failure */
+ return NULL;
+ }
+
+ if (fstat (info_fd, &stat_buf) != 0 || !S_ISREG (stat_buf.st_mode))
+ {
+ /* Some weird fd => failure */
+ close (info_fd);
+ return NULL;
+ }
+
+ mapped = g_mapped_file_new_from_fd (info_fd, FALSE, &local_error);
+ if (mapped == NULL)
+ {
+ close (info_fd);
+ return NULL;
+ }
+
+ if (!g_key_file_load_from_data (metadata,
+ g_mapped_file_get_contents (mapped),
+ g_mapped_file_get_length (mapped),
+ G_KEY_FILE_NONE, &local_error))
+ {
+ close (info_fd);
+ return NULL;
+ }
+
+ return g_steal_pointer (&metadata);
+}
- *dash = 0;
- xdg_id = g_strdup (name);
- }
+static char *
+get_xdg_id (guint32 pid)
+{
+ g_autoptr(GKeyFile) app_info = NULL;
- g_strfreev (lines);
+ app_info = parse_app_info_from_fileinfo (pid);
+ if (app_info == NULL)
+ return NULL;
- return xdg_id;
+ return g_key_file_get_string (app_info, "Application", "name", NULL);
}
static void
@@ -437,6 +474,8 @@ gclue_client_info_check_bus_name (GClueClientInfo *info,
return (strcmp (bus_name, info->priv->bus_name) == 0);
}
+/* Like parse_app_info_from_fileinfo(), returns NULL on failure,
+ * "" (an empty string) if not sandboxed, and a desktop ID otherwise */
const char *
gclue_client_info_get_xdg_id (GClueClientInfo *info)
{