File 0002-impl-link-only-check-permission-changes-for-owners.patch of Package pipewire.30043

From 6b5237b153c5b50956159d96a62a86fce670269f Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 20 Jul 2023 15:20:29 +0200
Subject: [PATCH] impl-link: only check permission changes for owners

When the permissions change on a node for a client, only check the
link permissions if the nodes of the link belong to the client.

Otherwise, we might destroy a link when the permissions are removed
from a node for an unrelated client.
---
 src/pipewire/impl-link.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c
index 74795ce28..30943a95f 100644
--- a/src/pipewire/impl-link.c
+++ b/src/pipewire/impl-link.c
@@ -1110,7 +1110,7 @@ static int check_owner_permissions(struct pw_context *context,
 		return -EIO;
 	if ((global = pw_context_find_global(context, client_id)) == NULL)
 		/* current client can't see the owner client */
-		return -ENOENT;
+		return -errno;
 	if (!pw_global_is_type(global, PW_TYPE_INTERFACE_Client) ||
 	    (client = global->object) == NULL)
 		/* not the right object, something wrong */
@@ -1118,7 +1118,7 @@ static int check_owner_permissions(struct pw_context *context,
 
 	if ((global = pw_context_find_global(context, id)) == NULL)
 		/* current client can't see node id */
-		return -ENOENT;
+		return -errno;
 
 	perms = pw_global_get_permissions(global, client);
 	if ((perms & permissions) != permissions)
@@ -1147,6 +1147,7 @@ check_permission(struct pw_context *context,
 static void permissions_changed(struct pw_impl_link *this, struct pw_impl_port *other,
 		struct pw_impl_client *client, uint32_t old, uint32_t new)
 {
+	int res;
 	uint32_t perm;
 
 	perm = pw_global_get_permissions(other->global, client);
@@ -1154,17 +1155,36 @@ static void permissions_changed(struct pw_impl_link *this, struct pw_impl_port *
 	new &= perm;
# 	pw_log_debug("%p: permissions changed %08x -> %08x", this, old, new);
 	pw_log_debug(NAME" %p: permissions changed %08x -> %08x", this, old, new);
 
-	if (check_permission(this->context, this->output, this->input, this->properties) < 0) {
+	if ((res = check_permission(this->context, this->output, this->input, this->properties)) < 0) {
+		pw_log_info("%p: link permissions removed: %s", this, spa_strerror(res));
 		pw_impl_link_destroy(this);
-	} else {
+	} else if (this->global != NULL) {
 		pw_global_update_permissions(this->global, client, old, new);
 	}
 }
 
+static bool is_port_owner(struct pw_impl_client *client, struct pw_impl_port *port)
+{
+	const char *str;
+	uint32_t client_id;
+
+	str = pw_properties_get(port->node->properties, PW_KEY_CLIENT_ID);
+	if (str == NULL)
+		return false;
+
+	if (!spa_atou32(str, &client_id, 0))
+		return false;
+
+	return client_id == client->info.id;
+}
+
 static void output_permissions_changed(void *data,
 		struct pw_impl_client *client, uint32_t old, uint32_t new)
 {
 	struct pw_impl_link *this = data;
+	if (!is_port_owner(client, this->output) &&
+	    !is_port_owner(client, this->input))
+		return;
 	permissions_changed(this, this->input, client, old, new);
 }
 
@@ -1177,6 +1197,9 @@ static void input_permissions_changed(void *data,
 		struct pw_impl_client *client, uint32_t old, uint32_t new)
 {
 	struct pw_impl_link *this = data;
+	if (!is_port_owner(client, this->output) &&
+	    !is_port_owner(client, this->input))
+		return;
 	permissions_changed(this, this->output, client, old, new);
 }
 
-- 
GitLab

openSUSE Build Service is sponsored by