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