mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									ab099d09dd
								
							
						
					
					
						commit
						ff17fb68b5
					
				
					 10 changed files with 32 additions and 21 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue