diff options
author | Alexander Larsson <alexl@redhat.com> | 2015-09-08 14:53:14 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2015-09-08 14:53:14 +0200 |
commit | 42c6cd4574e4b91aeda304a9f6f41bcee9834871 (patch) | |
tree | 830ff8142e54c4684ada942e0bfe832155a6a366 /document-portal | |
parent | fa3eb155805bf963bdec04d04eff0cb3310cdb3b (diff) | |
download | xdg-app-42c6cd4574e4b91aeda304a9f6f41bcee9834871.tar.gz |
document portal: Correctly handle recursive documents
I.e. if you pass in a document fd to the document portal we
reuse the existing id.
Diffstat (limited to 'document-portal')
-rw-r--r-- | document-portal/xdp-fuse.c | 12 | ||||
-rw-r--r-- | document-portal/xdp-fuse.h | 1 | ||||
-rw-r--r-- | document-portal/xdp-main.c | 78 |
3 files changed, 75 insertions, 16 deletions
diff --git a/document-portal/xdp-fuse.c b/document-portal/xdp-fuse.c index 7ad4a70..f4204db 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 16e08a8..b1e6c82 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 6b64f57..4decd24 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 (st_buf.st_dev == fuse_dev) + { + /* The passed in fd is on the fuse filesystem itself */ + guint32 old_id; + g_autoptr(XdgAppDbEntry) old_entry = NULL; + + 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; + } + + id = xdp_name_from_id (old_id); - if (app_id[0] != '\0') + /* 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 { - 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); + 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); } |