File 0001-impl-link-enforce-permissions-in-links.patch of Package pipewire.30045

From 0a214bf6b32ae72ec8b88d8446dde8b2f18a2852 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Mon, 17 Jul 2023 13:32:40 +0200
Subject: [PATCH] impl-link: enforce permissions in links

Enforce that the owner client of the output node can see the input node
and vice versa.

This works around an issue where the session manager performs a link
between nodes that should not be linked, like when doing screensharing
and the portal has set permissions to only see the screenshared stream,
wireplumber will link to the camera when the target.object is not set.
See also wireplumber#218

This has unfortunately the downside that patchbays like helvum will also
not be able to link those nodes. We should probably add a new link
permission to allow this explicitly.
---
 src/pipewire/impl-link.c | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c
index 23e4a3cd1e..74795ce280 100644
--- a/src/pipewire/impl-link.c
+++ b/src/pipewire/impl-link.c
@@ -1091,12 +1091,56 @@ static void try_unlink_controls(struct impl *impl, struct pw_impl_port *output,
 	}
 }
 
+static int check_owner_permissions(struct pw_context *context,
+		struct pw_impl_node *node, uint32_t id, uint32_t permissions)
+{
+	const char *str;
+	struct pw_impl_client *client;
+	struct pw_global *global;
+	uint32_t perms;
+	uint32_t client_id;
+
+	str = pw_properties_get(node->properties, PW_KEY_CLIENT_ID);
+	if (str == NULL)
+		/* node not owned by client */
+		return 0;
+
+	if (!spa_atou32(str, &client_id, 0))
+		/* invalid client_id, something is wrong */
+		return -EIO;
+	if ((global = pw_context_find_global(context, client_id)) == NULL)
+		/* current client can't see the owner client */
+		return -ENOENT;
+	if (!pw_global_is_type(global, PW_TYPE_INTERFACE_Client) ||
+	    (client = global->object) == NULL)
+		/* not the right object, something wrong */
+		return -EIO;
+
+	if ((global = pw_context_find_global(context, id)) == NULL)
+		/* current client can't see node id */
+		return -ENOENT;
+
+	perms = pw_global_get_permissions(global, client);
+	if ((perms & permissions) != permissions)
+		/* owner client can't see other node */
+		return -EPERM;
+
+	return 0;
+}
+
 static int
 check_permission(struct pw_context *context,
 		 struct pw_impl_port *output,
 		 struct pw_impl_port *input,
 		 struct pw_properties *properties)
 {
+	int res;
+	if ((res = check_owner_permissions(context, output->node,
+					input->node->info.id, PW_PERM_R)) < 0)
+		return res;
+	if ((res = check_owner_permissions(context, input->node,
+					output->node->info.id, PW_PERM_R)) < 0)
+		return res;
 	return 0;
 }
 
-- 
GitLab

openSUSE Build Service is sponsored by