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.
This commit is contained in:
Wim Taymans 2023-07-17 13:32:40 +02:00
parent 146665893e
commit 9e0932b319

View file

@ -1130,12 +1130,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;
}