From 0dfa05117bec16ee1817c3fa92f960a7d5e3b9b9 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sun, 8 Oct 2023 12:30:49 +0300 Subject: [PATCH] impl-client: fix client property update access check The `pipewire.*` properties may be set by clients but not changed by them. However, how the checks are done now this allows e.g. connecting clients to set `pipewire.access` themselves, which is not intended. Fix the client property update check to not allow clients to set pipewire.protocol/access, object.serial/id, pipewire.sec.* which are supposed to be set by the server. --- src/pipewire/impl-client.c | 45 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/pipewire/impl-client.c b/src/pipewire/impl-client.c index 14d903cab..53e7b7c82 100644 --- a/src/pipewire/impl-client.c +++ b/src/pipewire/impl-client.c @@ -152,30 +152,53 @@ static bool has_key(const char * const keys[], const char *key) return false; } -static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter) +static bool check_client_property_update(struct pw_impl_client *client, + const char *key, const char *old, const char *new) { static const char * const ignored[] = { + PW_KEY_PROTOCOL, PW_KEY_OBJECT_ID, + PW_KEY_OBJECT_SERIAL, + PW_KEY_ACCESS, NULL }; + /* Refuse specific restricted keys */ + if (has_key(ignored, key)) + goto deny; + + /* Refuse all security keys */ + if (spa_strstartswith(key, "pipewire.sec.")) + goto deny; + + /* Restrict other pipewire.* keys */ + if (spa_strstartswith(key, "pipewire.")) { + /* Refuse changing existing values */ + if (old != NULL) + goto deny; + } + + return true; + +deny: + if (!spa_streq(old, new)) + pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'", + client, key, old ? old : "", new ? new : ""); + return false; +} + +static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter) +{ struct pw_resource *resource; int changed = 0; uint32_t i; - const char *old; for (i = 0; i < dict->n_items; i++) { if (filter) { - if (spa_strstartswith(dict->items[i].key, "pipewire.") && - (old = pw_properties_get(client->properties, dict->items[i].key)) != NULL && - (dict->items[i].value == NULL || !spa_streq(old, dict->items[i].value))) { - pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'", - client, dict->items[i].key, old, - dict->items[i].value); - continue; + const char *old = pw_properties_get(client->properties, dict->items[i].key); + const char *new = dict->items[i].value; - } - if (has_key(ignored, dict->items[i].key)) + if (!check_client_property_update(client, dict->items[i].key, old, new)) continue; } changed += pw_properties_set(client->properties, dict->items[i].key, dict->items[i].value);