From 57096483afb069e69b9addcc39fe92b72051f1d2 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Tue, 24 Nov 2020 15:48:19 +0800 Subject: [PATCH] xdp-utils: check if alternate doc portal path matches in path_for_fd() The document portal uses different inode number when exposing a particular document in different parts of the file system. As sandboxed apps only have a subtree of the document portal file system mounted, the "same file" checks in xdp_app_info_get_path_for_fd() would fail for document portal paths. To fix this, we check to see whether the corresponding "by-app/$app_id" path matches the stat information of the file descriptor. Fixes #545 --- document-portal/document-portal.c | 2 ++ src/documents.c | 2 ++ src/xdp-utils.c | 47 +++++++++++++++++++++++++++++-- src/xdp-utils.h | 3 ++ 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/document-portal/document-portal.c b/document-portal/document-portal.c index a4c044a..a4aacc4 100644 --- a/document-portal/document-portal.c +++ b/document-portal/document-portal.c @@ -1448,6 +1448,8 @@ on_name_acquired (GDBusConnection *connection, fuse_dev = stbuf.st_dev; + xdp_set_documents_mountpoint (xdp_fuse_get_mountpoint ()); + while ((invocation = g_queue_pop_head (&get_mount_point_invocations)) != NULL) { xdp_dbus_documents_complete_get_mount_point (dbus_api, invocation, xdp_fuse_get_mountpoint ()); diff --git a/src/documents.c b/src/documents.c index 99de9e4..9ddc4ac 100644 --- a/src/documents.c +++ b/src/documents.c @@ -31,6 +31,7 @@ #include #include "xdp-dbus.h" +#include "xdp-utils.h" #include "document-enums.h" static XdpDocuments *documents = NULL; @@ -46,6 +47,7 @@ init_document_proxy (GDBusConnection *connection) xdp_documents_call_get_mount_point_sync (documents, &documents_mountpoint, NULL, NULL); + xdp_set_documents_mountpoint (documents_mountpoint); } char * diff --git a/src/xdp-utils.c b/src/xdp-utils.c index fa6ca6f..ef68f0f 100644 --- a/src/xdp-utils.c +++ b/src/xdp-utils.c @@ -884,6 +884,35 @@ verify_proc_self_fd (XdpAppInfo *app_info, return xdp_app_info_remap_path (app_info, path_buffer); } +static char *documents_mountpoint = NULL; + +void +xdp_set_documents_mountpoint (const char *path) +{ + g_clear_pointer (&documents_mountpoint, g_free); + documents_mountpoint = g_strdup (path); +} + +/* alternate_document_path converts a file path */ +char * +xdp_get_alternate_document_path (const char *path, const char *app_id) +{ + int len; + + /* If we don't know where the document portal is mounted, then there + * is no alternate path */ + if (documents_mountpoint == NULL) + return NULL; + + /* If the path is not within the document portal, then there is no + * alternative path */ + len = strlen (documents_mountpoint); + if (!g_str_has_prefix (path, documents_mountpoint) || path[len] != '/') + return NULL; + + return g_strconcat (documents_mountpoint, "/by-app/", app_id, &path[len], NULL); +} + char * xdp_app_info_get_path_for_fd (XdpAppInfo *app_info, int fd, @@ -981,8 +1010,22 @@ xdp_app_info_get_path_for_fd (XdpAppInfo *app_info, st_buf->st_dev != real_st_buf.st_dev || st_buf->st_ino != real_st_buf.st_ino) { - /* Different files on the inside and the outside, reject the request */ - return NULL; + /* If the path is provided by the document portal, the inode + number will not match, due to only a subtree being mounted in + the sandbox. So we check to see if the equivalent path + within that subtree matches our file descriptor. + + If the alternate path doesn't match either, then we treat it + as a failure. + */ + g_autofree char *alt_path = NULL; + alt_path = xdp_get_alternate_document_path (path, xdp_app_info_get_id (app_info)); + + if (alt_path == NULL || + stat (alt_path, &real_st_buf) < 0 || + st_buf->st_dev != real_st_buf.st_dev || + st_buf->st_ino != real_st_buf.st_ino) + return NULL; } if (writable_out) diff --git a/src/xdp-utils.h b/src/xdp-utils.h index 7105bce..fea28b8 100644 --- a/src/xdp-utils.h +++ b/src/xdp-utils.h @@ -88,6 +88,9 @@ char ** xdp_app_info_rewrite_commandline (XdpAppInfo *app_info, G_DEFINE_AUTOPTR_CLEANUP_FUNC(XdpAppInfo, xdp_app_info_unref) +void xdp_set_documents_mountpoint (const char *path); +char *xdp_get_alternate_document_path (const char *path, const char *app_id); + XdpAppInfo *xdp_invocation_lookup_app_info_sync (GDBusMethodInvocation *invocation, GCancellable *cancellable, GError **error);