From 42c6cd4574e4b91aeda304a9f6f41bcee9834871 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 8 Sep 2015 14:53:14 +0200 Subject: [PATCH] document portal: Correctly handle recursive documents I.e. if you pass in a document fd to the document portal we reuse the existing id. --- document-portal/xdp-fuse.c | 12 ++++++ document-portal/xdp-fuse.h | 1 + document-portal/xdp-main.c | 76 ++++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/document-portal/xdp-fuse.c b/document-portal/xdp-fuse.c index 7ad4a702..f4204dba 100644 --- a/document-portal/xdp-fuse.c +++ b/document-portal/xdp-fuse.c @@ -2170,6 +2170,18 @@ xdp_fuse_invalidate_doc (const char *doc_id_s, fuse_lowlevel_notify_inval_entry (main_ch, FUSE_ROOT_ID, doc_id_s, strlen (doc_id_s)); } +guint32 +xdp_fuse_lookup_id_for_inode (ino_t inode) +{ + XdpInodeClass class = get_class (inode); + guint64 class_ino = get_class_ino (inode); + + if (class != APP_DOC_FILE_INO_CLASS) + return 0; + + return get_doc_id_from_app_doc_ino (class_ino); +} + const char * xdp_fuse_get_mountpoint (void) { diff --git a/document-portal/xdp-fuse.h b/document-portal/xdp-fuse.h index 16e08a8c..b1e6c82f 100644 --- a/document-portal/xdp-fuse.h +++ b/document-portal/xdp-fuse.h @@ -18,6 +18,7 @@ void xdp_fuse_invalidate_doc_app (const char *doc_id, XdgAppDbEntry *entry); void xdp_fuse_invalidate_doc (const char *doc_id, XdgAppDbEntry *entry); +guint32 xdp_fuse_lookup_id_for_inode (ino_t inode); G_END_DECLS diff --git a/document-portal/xdp-main.c b/document-portal/xdp-main.c index 6b64f57f..4decd242 100644 --- a/document-portal/xdp-main.c +++ b/document-portal/xdp-main.c @@ -40,6 +40,7 @@ static XdgAppPermissionStore *permission_store; static GDBusNodeInfo *introspection_data = NULL; static int daemon_event_fd = -1; static int final_exit_status = 0; +static dev_t fuse_dev = 0; G_LOCK_DEFINE(db); @@ -383,23 +384,57 @@ portal_add (GDBusMethodInvocation *invocation, AUTOLOCK(db); - id = do_create_doc (&real_parent_st_buf, path_buffer, reuse_existing); - - if (app_id[0] != '\0') + if (st_buf.st_dev == fuse_dev) { - g_autoptr(XdgAppDbEntry) entry = NULL; - XdpPermissionFlags perms = - XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS | - XDP_PERMISSION_FLAGS_READ | - XDP_PERMISSION_FLAGS_WRITE; - entry = xdg_app_db_lookup (db, id); + /* The passed in fd is on the fuse filesystem itself */ + guint32 old_id; + g_autoptr(XdgAppDbEntry) old_entry = NULL; - /* If its a unique one its safe for the creator to - delete it at will */ - if (!reuse_existing) - perms |= XDP_PERMISSION_FLAGS_DELETE; + old_id = xdp_fuse_lookup_id_for_inode (st_buf.st_ino); + if (old_id == 0) + { + g_dbus_method_invocation_return_error (invocation, + XDG_APP_ERROR, XDG_APP_ERROR_INVALID_ARGUMENT, + "Invalid fd passed"); + return; + } - do_set_permissions (entry, id, app_id, perms); + id = xdp_name_from_id (old_id); + + /* If the entry doesn't exist anymore, fail. Also fail if not + resuse_existing, because otherwise the user could use this to + get a copy with permissions and thus escape later permission + revocations */ + old_entry = xdg_app_db_lookup (db, id); + if (old_entry == NULL || + !reuse_existing) + { + g_dbus_method_invocation_return_error (invocation, + XDG_APP_ERROR, XDG_APP_ERROR_INVALID_ARGUMENT, + "Invalid fd passed"); + return; + } + } + else + { + id = do_create_doc (&real_parent_st_buf, path_buffer, reuse_existing); + + if (app_id[0] != '\0') + { + g_autoptr(XdgAppDbEntry) entry = NULL; + XdpPermissionFlags perms = + XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS | + XDP_PERMISSION_FLAGS_READ | + XDP_PERMISSION_FLAGS_WRITE; + entry = xdg_app_db_lookup (db, id); + + /* If its a unique one its safe for the creator to + delete it at will */ + if (!reuse_existing) + perms |= XDP_PERMISSION_FLAGS_DELETE; + + do_set_permissions (entry, id, app_id, perms); + } } g_dbus_method_invocation_return_value (invocation, @@ -499,6 +534,7 @@ on_name_acquired (GDBusConnection *connection, gpointer user_data) { g_autoptr(GError) error = NULL; + struct stat stbuf; g_debug ("org.freedesktop.portal.Documents acquired"); @@ -510,6 +546,16 @@ on_name_acquired (GDBusConnection *connection, return; } + if (stat (xdp_fuse_get_mountpoint (), &stbuf) != 0) + { + final_exit_status = 7; + g_printerr ("fuse stat failed: %s\n", strerror (errno)); + g_main_loop_quit (loop); + return; + } + + fuse_dev = stbuf.st_dev; + daemon_report_done (0); } @@ -519,7 +565,7 @@ on_name_lost (GDBusConnection *connection, gpointer user_data) { g_debug ("org.freedesktop.portal.Documents lost"); - final_exit_status = 7; + final_exit_status = 20; g_main_loop_quit (loop); }