summaryrefslogtreecommitdiff
path: root/document-portal
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2015-09-08 14:53:14 +0200
committerAlexander Larsson <alexl@redhat.com>2015-09-08 14:53:14 +0200
commit42c6cd4574e4b91aeda304a9f6f41bcee9834871 (patch)
tree830ff8142e54c4684ada942e0bfe832155a6a366 /document-portal
parentfa3eb155805bf963bdec04d04eff0cb3310cdb3b (diff)
downloadxdg-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.c12
-rw-r--r--document-portal/xdp-fuse.h1
-rw-r--r--document-portal/xdp-main.c78
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);
}