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.
This commit is contained in:
Wim Taymans 2018-01-24 11:41:40 +01:00
parent ab099d09dd
commit ff17fb68b5
10 changed files with 32 additions and 21 deletions

View file

@ -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); 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) if (target == NULL)
goto error; goto error;

View file

@ -874,8 +874,11 @@ static int
process_messages(struct client *client) process_messages(struct client *client)
{ {
struct pw_client *c = client->client; struct pw_client *c = client->client;
struct pw_core *core = c->core;
int type, res = -1; int type, res = -1;
core->current_client = c;
if (read(client->fd, &type, sizeof(enum jack_request_type)) != sizeof(enum jack_request_type)) { 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); pw_log_error("protocol-jack %p: failed to read type", client->impl);
goto error; goto error;
@ -951,12 +954,15 @@ process_messages(struct client *client)
if (res != 0) if (res != 0)
goto error; goto error;
exit:
core->current_client = NULL;
return res; return res;
error: error:
pw_log_error("protocol-jack %p: error handling type %d", client->impl, type); pw_log_error("protocol-jack %p: error handling type %d", client->impl, type);
pw_client_destroy(c); 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_audio_client(impl);
make_freewheel_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; return true;
} }

View file

@ -83,13 +83,13 @@ static void *create_object(void *_data,
core = pw_client_get_core(client); core = pw_client_get_core(client);
t = pw_core_get_type(core); 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) if (global == NULL || pw_global_get_type(global) != t->node)
goto no_output; goto no_output;
output_node = pw_global_get_object(global); 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) if (global == NULL || pw_global_get_type(global) != t->node)
goto no_input; goto no_input;

View file

@ -233,7 +233,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie
spa_list_init(&impl->node_list); 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_core_add_listener(core, &impl->core_listener, &core_events, impl);
pw_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_module_add_listener(module, &impl->module_listener, &module_events, impl);

View file

@ -168,11 +168,14 @@ process_messages(struct client_data *data)
{ {
struct pw_protocol_native_connection *conn = data->connection; struct pw_protocol_native_connection *conn = data->connection;
struct pw_client *client = data->client; struct pw_client *client = data->client;
struct pw_core *core = client->core;
uint8_t opcode; uint8_t opcode;
uint32_t id; uint32_t id;
uint32_t size; uint32_t size;
void *message; void *message;
core->current_client = client;
while (pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size)) { while (pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size)) {
struct pw_resource *resource; struct pw_resource *resource;
const struct pw_protocol_native_demarshal *demarshal; 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) if (demarshal[opcode].func(resource, message, size) < 0)
goto invalid_message; goto invalid_message;
} }
done:
core->current_client = NULL;
return; return;
invalid_method: invalid_method:
pw_log_error("protocol-native %p: invalid method %u on resource %u", pw_log_error("protocol-native %p: invalid method %u on resource %u",
client->protocol, opcode, id); client->protocol, opcode, id);
pw_client_destroy(client); pw_client_destroy(client);
return; goto done;
invalid_message: invalid_message:
pw_log_error("protocol-native %p: invalid message received %u %u", pw_log_error("protocol-native %p: invalid message received %u %u",
client->protocol, id, opcode); client->protocol, id, opcode);
pw_client_destroy(client); pw_client_destroy(client);
return; goto done;
} }
static void static void

View file

@ -449,7 +449,7 @@ int pw_client_update_permissions(struct pw_client *client, const struct spa_dict
continue; continue;
global_id = atoi(str); 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) { if (global == NULL) {
pw_log_warn("client %p: invalid global %d", client, global_id); pw_log_warn("client %p: invalid global %d", client, global_id);
continue; continue;
@ -473,7 +473,7 @@ int pw_client_update_permissions(struct pw_client *client, const struct spa_dict
if (permissions_existing != -1) { if (permissions_existing != -1) {
update.permissions = permissions_existing; update.permissions = permissions_existing;
update.only_new = true; 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; impl->permissions_default = permissions_default;

View file

@ -51,7 +51,7 @@ static void registry_bind(void *object, uint32_t id,
struct pw_global *global; struct pw_global *global;
uint32_t permissions; 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; goto no_id;
permissions = pw_global_get_permissions(global, client); 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, int pw_core_for_each_global(struct pw_core *core,
struct pw_client *client,
int (*callback) (void *data, struct pw_global *global), int (*callback) (void *data, struct pw_global *global),
void *data) void *data)
{ {
@ -555,7 +554,8 @@ int pw_core_for_each_global(struct pw_core *core,
int res; int res;
spa_list_for_each_safe(g, t, &core->global_list, link) { 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; continue;
if ((res = callback(data, g)) != 0) if ((res = callback(data, g)) != 0)
return res; return res;
@ -563,7 +563,7 @@ int pw_core_for_each_global(struct pw_core *core,
return 0; 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; 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) if (global == NULL)
return 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 NULL;
return global; return global;
@ -591,7 +592,6 @@ struct pw_global *pw_core_find_global(struct pw_core *core, struct pw_client *cl
* \memberof pw_core * \memberof pw_core
*/ */
struct pw_port *pw_core_find_port(struct pw_core *core, struct pw_port *pw_core_find_port(struct pw_core *core,
struct pw_client *client,
struct pw_port *other_port, struct pw_port *other_port,
uint32_t id, uint32_t id,
struct pw_properties *props, struct pw_properties *props,
@ -614,7 +614,8 @@ struct pw_port *pw_core_find_port(struct pw_core *core,
if (other_port->node == n) if (other_port->node == n)
continue; 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; continue;
pw_log_debug("node id \"%d\"", n->global->id); pw_log_debug("node id \"%d\"", n->global->id);

View file

@ -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 * the value. When all callbacks return 0, this function returns 0 when all
* globals are iterated. */ * globals are iterated. */
int pw_core_for_each_global(struct pw_core *core, /**< the core */ 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), int (*callback) (void *data, struct pw_global *global),
void *data); void *data);
/** Find a core global by id */ /** Find a core global by id */
struct pw_global *pw_core_find_global(struct pw_core *core, /**< the core */ 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 */); uint32_t id /**< the global id */);
/** Find a factory by name */ /** Find a factory by name */

View file

@ -153,6 +153,8 @@ struct pw_core {
struct spa_support support[16]; /**< support for spa plugins */ struct spa_support support[16]; /**< support for spa plugins */
uint32_t n_support; /**< number of support items */ uint32_t n_support; /**< number of support items */
struct pw_client *current_client; /**< client currently executing code in mainloop */
long sc_pagesize; long sc_pagesize;
struct { 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 */ /** Find a ports compatible with \a other_port and the format filters */
struct pw_port * struct pw_port *
pw_core_find_port(struct pw_core *core, pw_core_find_port(struct pw_core *core,
struct pw_client *client,
struct pw_port *other_port, struct pw_port *other_port,
uint32_t id, uint32_t id,
struct pw_properties *props, struct pw_properties *props,

View file

@ -1001,7 +1001,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
goto no_remote; 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) { if (global == NULL) {
asprintf(error, "object %d does not exist", atoi(a[0])); asprintf(error, "object %d does not exist", atoi(a[0]));
return false; return false;