From ff17fb68b50f971b72fdf325259107d0acaa475d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 24 Jan 2018 11:41:40 +0100 Subject: [PATCH] permissions: use current_client for security checks Don't pass around the client object but keep track of the current client in the core object. This way we don't need to add a client argument to functions and can check security when needed. --- src/modules/module-autolink.c | 2 +- src/modules/module-jack.c | 10 ++++++++-- src/modules/module-link-factory.c | 4 ++-- src/modules/module-mixer.c | 2 +- src/modules/module-protocol-native.c | 9 +++++++-- src/pipewire/client.c | 4 ++-- src/pipewire/core.c | 15 ++++++++------- src/pipewire/core.h | 2 -- src/pipewire/private.h | 3 ++- src/tools/pipewire-cli.c | 2 +- 10 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/modules/module-autolink.c b/src/modules/module-autolink.c index 356327fea..2a9a11d7b 100644 --- a/src/modules/module-autolink.c +++ b/src/modules/module-autolink.c @@ -204,7 +204,7 @@ static void try_link_port(struct pw_node *node, struct pw_port *port, struct nod pw_log_debug("module %p: try to find and link to node '%d'", impl, path_id); - target = pw_core_find_port(impl->core, owner, port, path_id, NULL, 0, NULL, &error); + target = pw_core_find_port(impl->core, port, path_id, NULL, 0, NULL, &error); if (target == NULL) goto error; diff --git a/src/modules/module-jack.c b/src/modules/module-jack.c index 58f3ff950..f235a04dd 100644 --- a/src/modules/module-jack.c +++ b/src/modules/module-jack.c @@ -874,8 +874,11 @@ static int process_messages(struct client *client) { struct pw_client *c = client->client; + struct pw_core *core = c->core; int type, res = -1; + core->current_client = c; + if (read(client->fd, &type, sizeof(enum jack_request_type)) != sizeof(enum jack_request_type)) { pw_log_error("protocol-jack %p: failed to read type", client->impl); goto error; @@ -951,12 +954,15 @@ process_messages(struct client *client) if (res != 0) goto error; + exit: + core->current_client = NULL; return res; error: pw_log_error("protocol-jack %p: error handling type %d", client->impl, type); pw_client_destroy(c); - return -1; + res = -EIO; + goto exit; } @@ -1351,7 +1357,7 @@ static bool init_nodes(struct impl *impl) make_audio_client(impl); make_freewheel_client(impl); - pw_core_for_each_global(core, NULL, on_global, impl); + pw_core_for_each_global(core, on_global, impl); return true; } diff --git a/src/modules/module-link-factory.c b/src/modules/module-link-factory.c index 9c1219ffc..5be8d5a79 100644 --- a/src/modules/module-link-factory.c +++ b/src/modules/module-link-factory.c @@ -83,13 +83,13 @@ static void *create_object(void *_data, core = pw_client_get_core(client); t = pw_core_get_type(core); - global = pw_core_find_global(core, client, output_node_id); + global = pw_core_find_global(core, output_node_id); if (global == NULL || pw_global_get_type(global) != t->node) goto no_output; output_node = pw_global_get_object(global); - global = pw_core_find_global(core, client, input_node_id); + global = pw_core_find_global(core, input_node_id); if (global == NULL || pw_global_get_type(global) != t->node) goto no_input; diff --git a/src/modules/module-mixer.c b/src/modules/module-mixer.c index 5dd51298b..f3c1a2f34 100644 --- a/src/modules/module-mixer.c +++ b/src/modules/module-mixer.c @@ -233,7 +233,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie spa_list_init(&impl->node_list); - pw_core_for_each_global(core, NULL, on_global, impl); + pw_core_for_each_global(core, on_global, impl); pw_core_add_listener(core, &impl->core_listener, &core_events, impl); pw_module_add_listener(module, &impl->module_listener, &module_events, impl); diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c index 4eecc550b..4393be23f 100644 --- a/src/modules/module-protocol-native.c +++ b/src/modules/module-protocol-native.c @@ -168,11 +168,14 @@ process_messages(struct client_data *data) { struct pw_protocol_native_connection *conn = data->connection; struct pw_client *client = data->client; + struct pw_core *core = client->core; uint8_t opcode; uint32_t id; uint32_t size; void *message; + core->current_client = client; + while (pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size)) { struct pw_resource *resource; const struct pw_protocol_native_demarshal *demarshal; @@ -222,18 +225,20 @@ process_messages(struct client_data *data) if (demarshal[opcode].func(resource, message, size) < 0) goto invalid_message; } + done: + core->current_client = NULL; return; invalid_method: pw_log_error("protocol-native %p: invalid method %u on resource %u", client->protocol, opcode, id); pw_client_destroy(client); - return; + goto done; invalid_message: pw_log_error("protocol-native %p: invalid message received %u %u", client->protocol, id, opcode); pw_client_destroy(client); - return; + goto done; } static void diff --git a/src/pipewire/client.c b/src/pipewire/client.c index 02bd943a4..998d867d5 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -449,7 +449,7 @@ int pw_client_update_permissions(struct pw_client *client, const struct spa_dict continue; global_id = atoi(str); - global = pw_core_find_global(client->core, client, global_id); + global = pw_core_find_global(client->core, global_id); if (global == NULL) { pw_log_warn("client %p: invalid global %d", client, global_id); continue; @@ -473,7 +473,7 @@ int pw_client_update_permissions(struct pw_client *client, const struct spa_dict if (permissions_existing != -1) { update.permissions = permissions_existing; update.only_new = true; - pw_core_for_each_global(client->core, client, do_permissions, &update); + pw_core_for_each_global(client->core, do_permissions, &update); } impl->permissions_default = permissions_default; diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 611a91a47..f57bb14d0 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -51,7 +51,7 @@ static void registry_bind(void *object, uint32_t id, struct pw_global *global; uint32_t permissions; - if ((global = pw_core_find_global(core, NULL, id)) == NULL) + if ((global = pw_core_find_global(core, id)) == NULL) goto no_id; permissions = pw_global_get_permissions(global, client); @@ -547,7 +547,6 @@ int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict) } int pw_core_for_each_global(struct pw_core *core, - struct pw_client *client, int (*callback) (void *data, struct pw_global *global), void *data) { @@ -555,7 +554,8 @@ int pw_core_for_each_global(struct pw_core *core, int res; spa_list_for_each_safe(g, t, &core->global_list, link) { - if (client && !PW_PERM_IS_R(pw_global_get_permissions(g, client))) + if (core->current_client && + !PW_PERM_IS_R(pw_global_get_permissions(g, core->current_client))) continue; if ((res = callback(data, g)) != 0) return res; @@ -563,7 +563,7 @@ int pw_core_for_each_global(struct pw_core *core, return 0; } -struct pw_global *pw_core_find_global(struct pw_core *core, struct pw_client *client, uint32_t id) +struct pw_global *pw_core_find_global(struct pw_core *core, uint32_t id) { struct pw_global *global; @@ -571,7 +571,8 @@ struct pw_global *pw_core_find_global(struct pw_core *core, struct pw_client *cl if (global == NULL) return NULL; - if (client && !PW_PERM_IS_R(pw_global_get_permissions(global, client))) + if (core->current_client && + !PW_PERM_IS_R(pw_global_get_permissions(global, core->current_client))) return NULL; return global; @@ -591,7 +592,6 @@ struct pw_global *pw_core_find_global(struct pw_core *core, struct pw_client *cl * \memberof pw_core */ struct pw_port *pw_core_find_port(struct pw_core *core, - struct pw_client *client, struct pw_port *other_port, uint32_t id, struct pw_properties *props, @@ -614,7 +614,8 @@ struct pw_port *pw_core_find_port(struct pw_core *core, if (other_port->node == n) continue; - if (!PW_PERM_IS_R(pw_global_get_permissions(n->global, client))) + if (core->current_client && + !PW_PERM_IS_R(pw_global_get_permissions(n->global, core->current_client))) continue; pw_log_debug("node id \"%d\"", n->global->id); diff --git a/src/pipewire/core.h b/src/pipewire/core.h index d9ed4c502..ab0d81d90 100644 --- a/src/pipewire/core.h +++ b/src/pipewire/core.h @@ -160,13 +160,11 @@ struct pw_loop *pw_core_get_main_loop(struct pw_core *core); * the value. When all callbacks return 0, this function returns 0 when all * globals are iterated. */ int pw_core_for_each_global(struct pw_core *core, /**< the core */ - struct pw_client *client, /**< optional client */ int (*callback) (void *data, struct pw_global *global), void *data); /** Find a core global by id */ struct pw_global *pw_core_find_global(struct pw_core *core, /**< the core */ - struct pw_client *client, /**< optional client */ uint32_t id /**< the global id */); /** Find a factory by name */ diff --git a/src/pipewire/private.h b/src/pipewire/private.h index d79526bb4..b96d758a2 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -153,6 +153,8 @@ struct pw_core { struct spa_support support[16]; /**< support for spa plugins */ uint32_t n_support; /**< number of support items */ + struct pw_client *current_client; /**< client currently executing code in mainloop */ + long sc_pagesize; struct { @@ -434,7 +436,6 @@ int pw_core_find_format(struct pw_core *core, /** Find a ports compatible with \a other_port and the format filters */ struct pw_port * pw_core_find_port(struct pw_core *core, - struct pw_client *client, struct pw_port *other_port, uint32_t id, struct pw_properties *props, diff --git a/src/tools/pipewire-cli.c b/src/tools/pipewire-cli.c index 2d2dfa70d..83a4ad67b 100644 --- a/src/tools/pipewire-cli.c +++ b/src/tools/pipewire-cli.c @@ -1001,7 +1001,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char goto no_remote; } - global = pw_core_find_global(data->core, NULL, atoi(a[0])); + global = pw_core_find_global(data->core, atoi(a[0])); if (global == NULL) { asprintf(error, "object %d does not exist", atoi(a[0])); return false;