mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
context: move registry generation checks to context methods
Add registry generation checks to pw_context methods that find globals, (pw_context_find_global, pw_context_for_each_global), so that they are made everywhere where a client acquires globals. In addition to previously covered registry bind/destroy, this also covers link creation (port/node ids) and metadata (subject ids).
This commit is contained in:
parent
a59a551202
commit
651cb7bd71
3 changed files with 44 additions and 26 deletions
|
|
@ -553,6 +553,19 @@ static bool global_can_read(struct pw_context *context, struct pw_global *global
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool global_is_stale(struct pw_context *context, struct pw_global *global)
|
||||||
|
{
|
||||||
|
struct pw_impl_client *client = context->current_client;
|
||||||
|
|
||||||
|
if (!client)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (client->recv_generation != 0 && global->generation > client->recv_generation)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
int pw_context_for_each_global(struct pw_context *context,
|
int pw_context_for_each_global(struct pw_context *context,
|
||||||
int (*callback) (void *data, struct pw_global *global),
|
int (*callback) (void *data, struct pw_global *global),
|
||||||
|
|
@ -562,7 +575,7 @@ int pw_context_for_each_global(struct pw_context *context,
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
spa_list_for_each_safe(g, t, &context->global_list, link) {
|
spa_list_for_each_safe(g, t, &context->global_list, link) {
|
||||||
if (!global_can_read(context, g))
|
if (!global_can_read(context, g) || global_is_stale(context, g))
|
||||||
continue;
|
continue;
|
||||||
if ((res = callback(data, g)) != 0)
|
if ((res = callback(data, g)) != 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -581,6 +594,11 @@ struct pw_global *pw_context_find_global(struct pw_context *context, uint32_t id
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (global_is_stale(context, global)) {
|
||||||
|
errno = global_can_read(context, global) ? ESTALE : ENOENT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!global_can_read(context, global)) {
|
if (!global_can_read(context, global)) {
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -117,15 +117,16 @@ static int client_error(void *object, uint32_t id, int res, const char *error)
|
||||||
struct pw_impl_client *sender = resource->client;
|
struct pw_impl_client *sender = resource->client;
|
||||||
struct pw_impl_client *client = data->client;
|
struct pw_impl_client *client = data->client;
|
||||||
struct error_data d = { id, res, error };
|
struct error_data d = { id, res, error };
|
||||||
struct pw_global *global;
|
|
||||||
|
|
||||||
/* Check the global id provided by sender refers to a registered global
|
/* Check the global id provided by sender refers to a registered global
|
||||||
* known to the sender.
|
* known to the sender.
|
||||||
*/
|
*/
|
||||||
if ((global = pw_context_find_global(resource->context, id)) == NULL)
|
if (pw_context_find_global(resource->context, id) == NULL) {
|
||||||
goto error_no_id;
|
if (errno == ESTALE)
|
||||||
if (sender->recv_generation != 0 && global->generation > sender->recv_generation)
|
goto error_stale_id;
|
||||||
goto error_stale_id;
|
else
|
||||||
|
goto error_no_id;
|
||||||
|
}
|
||||||
|
|
||||||
pw_log_debug("%p: sender %p: error for global %u", client, sender, id);
|
pw_log_debug("%p: sender %p: error for global %u", client, sender, id);
|
||||||
pw_map_for_each(&client->objects, error_resource, &d);
|
pw_map_for_each(&client->objects, error_resource, &d);
|
||||||
|
|
@ -136,8 +137,8 @@ error_no_id:
|
||||||
pw_resource_errorf(resource, -ENOENT, "no global %u", id);
|
pw_resource_errorf(resource, -ENOENT, "no global %u", id);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
error_stale_id:
|
error_stale_id:
|
||||||
pw_log_debug("%p: sender %p: error for stale global %u generation:%"PRIu64" recv-generation:%"PRIu64,
|
pw_log_debug("%p: sender %p: error for stale global %u recv-generation:%"PRIu64,
|
||||||
client, sender, id, global->generation, sender->recv_generation);
|
client, sender, id, sender->recv_generation);
|
||||||
pw_resource_errorf(resource, -ESTALE, "no global %u any more", id);
|
pw_resource_errorf(resource, -ESTALE, "no global %u any more", id);
|
||||||
return -ESTALE;
|
return -ESTALE;
|
||||||
}
|
}
|
||||||
|
|
@ -804,10 +805,7 @@ int pw_impl_client_check_permissions(struct pw_impl_client *client,
|
||||||
uint32_t perms;
|
uint32_t perms;
|
||||||
|
|
||||||
if ((global = pw_context_find_global(context, global_id)) == NULL)
|
if ((global = pw_context_find_global(context, global_id)) == NULL)
|
||||||
return -ENOENT;
|
return (errno == ESTALE) ? -ESTALE : -ENOENT;
|
||||||
|
|
||||||
if (client->recv_generation != 0 && global->generation > client->recv_generation)
|
|
||||||
return -ESTALE;
|
|
||||||
|
|
||||||
perms = pw_global_get_permissions(global, client);
|
perms = pw_global_get_permissions(global, client);
|
||||||
if ((perms & permissions) != permissions)
|
if ((perms & permissions) != permissions)
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,18 @@ static void * registry_bind(void *object, uint32_t id,
|
||||||
struct pw_global *global;
|
struct pw_global *global;
|
||||||
uint32_t permissions, new_id = user_data_size;
|
uint32_t permissions, new_id = user_data_size;
|
||||||
|
|
||||||
if ((global = pw_context_find_global(context, id)) == NULL)
|
if ((global = pw_context_find_global(context, id)) == NULL) {
|
||||||
goto error_no_id;
|
if (errno == ESTALE)
|
||||||
|
goto error_stale_id;
|
||||||
|
else
|
||||||
|
goto error_no_id;
|
||||||
|
}
|
||||||
|
|
||||||
permissions = pw_global_get_permissions(global, client);
|
permissions = pw_global_get_permissions(global, client);
|
||||||
|
|
||||||
if (!PW_PERM_IS_R(permissions))
|
if (!PW_PERM_IS_R(permissions))
|
||||||
goto error_no_id;
|
goto error_no_id;
|
||||||
|
|
||||||
if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation)
|
|
||||||
goto error_stale_id;
|
|
||||||
|
|
||||||
if (!spa_streq(global->type, type))
|
if (!spa_streq(global->type, type))
|
||||||
goto error_wrong_interface;
|
goto error_wrong_interface;
|
||||||
|
|
||||||
|
|
@ -57,8 +58,8 @@ static void * registry_bind(void *object, uint32_t id,
|
||||||
|
|
||||||
error_stale_id:
|
error_stale_id:
|
||||||
pw_log_debug("registry %p: not binding stale global "
|
pw_log_debug("registry %p: not binding stale global "
|
||||||
"id %u to %u, generation:%"PRIu64" recv-generation:%"PRIu64,
|
"id %u to %u recv-generation:%"PRIu64,
|
||||||
resource, id, new_id, global->generation, resource->client->recv_generation);
|
resource, id, new_id, resource->client->recv_generation);
|
||||||
pw_resource_errorf_id(resource, new_id, -ESTALE, "no global %u any more", id);
|
pw_resource_errorf_id(resource, new_id, -ESTALE, "no global %u any more", id);
|
||||||
goto error_exit_clean;
|
goto error_exit_clean;
|
||||||
error_no_id:
|
error_no_id:
|
||||||
|
|
@ -88,17 +89,18 @@ static int registry_destroy(void *object, uint32_t id)
|
||||||
uint32_t permissions;
|
uint32_t permissions;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((global = pw_context_find_global(context, id)) == NULL)
|
if ((global = pw_context_find_global(context, id)) == NULL) {
|
||||||
goto error_no_id;
|
if (errno == ESTALE)
|
||||||
|
goto error_stale_id;
|
||||||
|
else
|
||||||
|
goto error_no_id;
|
||||||
|
}
|
||||||
|
|
||||||
permissions = pw_global_get_permissions(global, client);
|
permissions = pw_global_get_permissions(global, client);
|
||||||
|
|
||||||
if (!PW_PERM_IS_R(permissions))
|
if (!PW_PERM_IS_R(permissions))
|
||||||
goto error_no_id;
|
goto error_no_id;
|
||||||
|
|
||||||
if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation)
|
|
||||||
goto error_stale_id;
|
|
||||||
|
|
||||||
if (id == PW_ID_CORE || !PW_PERM_IS_X(permissions))
|
if (id == PW_ID_CORE || !PW_PERM_IS_X(permissions))
|
||||||
goto error_not_allowed;
|
goto error_not_allowed;
|
||||||
|
|
||||||
|
|
@ -109,8 +111,8 @@ static int registry_destroy(void *object, uint32_t id)
|
||||||
|
|
||||||
error_stale_id:
|
error_stale_id:
|
||||||
pw_log_debug("registry %p: not destroying stale global "
|
pw_log_debug("registry %p: not destroying stale global "
|
||||||
"id %u, generation:%"PRIu64" recv-generation:%"PRIu64,
|
"id %u, recv-generation:%"PRIu64,
|
||||||
resource, id, global->generation, resource->client->recv_generation);
|
resource, id, resource->client->recv_generation);
|
||||||
pw_resource_errorf(resource, -ESTALE, "no global %u any more", id);
|
pw_resource_errorf(resource, -ESTALE, "no global %u any more", id);
|
||||||
res = -ESTALE;
|
res = -ESTALE;
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue