mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Add a "side" field and some sanity checks to wl_map.
The original wl_map implementation did no checking to ensures that ids fell on the correct side of the WL_SERVER_ID_START line. This meant that a client could send the server a server ID and it would happily try to use it. Also, there was no distinction between server-side and client-side in wl_map_remove. Because wl_map_remove added the entry to the free list regardless of which side it came from, the following set of actions would break the map: 1. Client creates a bunch of objects 2. Client deletes one or more of those objects 3. Client does something that causes the server to create an object Because of the problem in wl_map_remove, the server would take an old client-side id, apply the WL_SERVER_ID_START offset, and try to use it as a server-side id regardless of whether or not it was valid. Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
		
							parent
							
								
									dce104dcc2
								
							
						
					
					
						commit
						28472970df
					
				
					 4 changed files with 32 additions and 15 deletions
				
			
		| 
						 | 
					@ -226,8 +226,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
 | 
				
			||||||
	proxy->refcount = 1;
 | 
						proxy->refcount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pthread_mutex_lock(&display->mutex);
 | 
						pthread_mutex_lock(&display->mutex);
 | 
				
			||||||
	proxy->object.id = wl_map_insert_new(&display->objects,
 | 
						proxy->object.id = wl_map_insert_new(&display->objects, proxy);
 | 
				
			||||||
					     WL_MAP_CLIENT_SIDE, proxy);
 | 
					 | 
				
			||||||
	pthread_mutex_unlock(&display->mutex);
 | 
						pthread_mutex_unlock(&display->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return proxy;
 | 
						return proxy;
 | 
				
			||||||
| 
						 | 
					@ -518,17 +517,16 @@ wl_display_connect_to_fd(int fd)
 | 
				
			||||||
	memset(display, 0, sizeof *display);
 | 
						memset(display, 0, sizeof *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display->fd = fd;
 | 
						display->fd = fd;
 | 
				
			||||||
	wl_map_init(&display->objects);
 | 
						wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
 | 
				
			||||||
	wl_event_queue_init(&display->queue, display);
 | 
						wl_event_queue_init(&display->queue, display);
 | 
				
			||||||
	wl_list_init(&display->event_queue_list);
 | 
						wl_list_init(&display->event_queue_list);
 | 
				
			||||||
	pthread_mutex_init(&display->mutex, NULL);
 | 
						pthread_mutex_init(&display->mutex, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_map_insert_new(&display->objects, WL_MAP_CLIENT_SIDE, NULL);
 | 
						wl_map_insert_new(&display->objects, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display->proxy.object.interface = &wl_display_interface;
 | 
						display->proxy.object.interface = &wl_display_interface;
 | 
				
			||||||
	display->proxy.object.id =
 | 
						display->proxy.object.id =
 | 
				
			||||||
		wl_map_insert_new(&display->objects,
 | 
							wl_map_insert_new(&display->objects, display);
 | 
				
			||||||
				  WL_MAP_CLIENT_SIDE, display);
 | 
					 | 
				
			||||||
	display->proxy.display = display;
 | 
						display->proxy.display = display;
 | 
				
			||||||
	display->proxy.object.implementation = (void(**)(void)) &display_listener;
 | 
						display->proxy.object.implementation = (void(**)(void)) &display_listener;
 | 
				
			||||||
	display->proxy.user_data = display;
 | 
						display->proxy.user_data = display;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,14 +44,15 @@
 | 
				
			||||||
struct wl_map {
 | 
					struct wl_map {
 | 
				
			||||||
	struct wl_array client_entries;
 | 
						struct wl_array client_entries;
 | 
				
			||||||
	struct wl_array server_entries;
 | 
						struct wl_array server_entries;
 | 
				
			||||||
 | 
						uint32_t side;
 | 
				
			||||||
	uint32_t free_list;
 | 
						uint32_t free_list;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*wl_iterator_func_t)(void *element, void *data);
 | 
					typedef void (*wl_iterator_func_t)(void *element, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wl_map_init(struct wl_map *map);
 | 
					void wl_map_init(struct wl_map *map, uint32_t side);
 | 
				
			||||||
void wl_map_release(struct wl_map *map);
 | 
					void wl_map_release(struct wl_map *map);
 | 
				
			||||||
uint32_t wl_map_insert_new(struct wl_map *map, uint32_t side, void *data);
 | 
					uint32_t wl_map_insert_new(struct wl_map *map, void *data);
 | 
				
			||||||
int wl_map_insert_at(struct wl_map *map, uint32_t i, void *data);
 | 
					int wl_map_insert_at(struct wl_map *map, uint32_t i, void *data);
 | 
				
			||||||
int wl_map_reserve_new(struct wl_map *map, uint32_t i);
 | 
					int wl_map_reserve_new(struct wl_map *map, uint32_t i);
 | 
				
			||||||
void wl_map_remove(struct wl_map *map, uint32_t i);
 | 
					void wl_map_remove(struct wl_map *map, uint32_t i);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -336,7 +336,7 @@ wl_client_create(struct wl_display *display, int fd)
 | 
				
			||||||
	if (client->connection == NULL)
 | 
						if (client->connection == NULL)
 | 
				
			||||||
		goto err_source;
 | 
							goto err_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_map_init(&client->objects);
 | 
						wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wl_map_insert_at(&client->objects, 0, NULL) < 0)
 | 
						if (wl_map_insert_at(&client->objects, 0, NULL) < 0)
 | 
				
			||||||
		goto err_map;
 | 
							goto err_map;
 | 
				
			||||||
| 
						 | 
					@ -379,8 +379,7 @@ wl_client_add_resource(struct wl_client *client,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (resource->object.id == 0) {
 | 
						if (resource->object.id == 0) {
 | 
				
			||||||
		resource->object.id =
 | 
							resource->object.id =
 | 
				
			||||||
			wl_map_insert_new(&client->objects,
 | 
								wl_map_insert_new(&client->objects, resource);
 | 
				
			||||||
					  WL_MAP_SERVER_SIDE, resource);
 | 
					 | 
				
			||||||
	} else if (wl_map_insert_at(&client->objects,
 | 
						} else if (wl_map_insert_at(&client->objects,
 | 
				
			||||||
				  resource->object.id, resource) < 0) {
 | 
									  resource->object.id, resource) < 0) {
 | 
				
			||||||
		wl_resource_post_error(client->display_resource,
 | 
							wl_resource_post_error(client->display_resource,
 | 
				
			||||||
| 
						 | 
					@ -932,7 +931,7 @@ wl_client_new_object(struct wl_client *client,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t id;
 | 
						uint32_t id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	id = wl_map_insert_new(&client->objects, WL_MAP_SERVER_SIDE, NULL);
 | 
						id = wl_map_insert_new(&client->objects, NULL);
 | 
				
			||||||
	return wl_client_add_object(client,
 | 
						return wl_client_add_object(client,
 | 
				
			||||||
				    interface, implementation, id, data);
 | 
									    interface, implementation, id, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,9 +152,10 @@ union map_entry {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT void
 | 
					WL_EXPORT void
 | 
				
			||||||
wl_map_init(struct wl_map *map)
 | 
					wl_map_init(struct wl_map *map, uint32_t side)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	memset(map, 0, sizeof *map);
 | 
						memset(map, 0, sizeof *map);
 | 
				
			||||||
 | 
						map->side = side;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT void
 | 
					WL_EXPORT void
 | 
				
			||||||
| 
						 | 
					@ -165,13 +166,13 @@ wl_map_release(struct wl_map *map)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT uint32_t
 | 
					WL_EXPORT uint32_t
 | 
				
			||||||
wl_map_insert_new(struct wl_map *map, uint32_t side, void *data)
 | 
					wl_map_insert_new(struct wl_map *map, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	union map_entry *start, *entry;
 | 
						union map_entry *start, *entry;
 | 
				
			||||||
	struct wl_array *entries;
 | 
						struct wl_array *entries;
 | 
				
			||||||
	uint32_t base;
 | 
						uint32_t base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (side == WL_MAP_CLIENT_SIDE) {
 | 
						if (map->side == WL_MAP_CLIENT_SIDE) {
 | 
				
			||||||
		entries = &map->client_entries;
 | 
							entries = &map->client_entries;
 | 
				
			||||||
		base = 0;
 | 
							base = 0;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -203,8 +204,14 @@ wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
 | 
				
			||||||
	struct wl_array *entries;
 | 
						struct wl_array *entries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < WL_SERVER_ID_START) {
 | 
						if (i < WL_SERVER_ID_START) {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_CLIENT_SIDE)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->client_entries;
 | 
							entries = &map->client_entries;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_SERVER_SIDE)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->server_entries;
 | 
							entries = &map->server_entries;
 | 
				
			||||||
		i -= WL_SERVER_ID_START;
 | 
							i -= WL_SERVER_ID_START;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -230,8 +237,14 @@ wl_map_reserve_new(struct wl_map *map, uint32_t i)
 | 
				
			||||||
	struct wl_array *entries;
 | 
						struct wl_array *entries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < WL_SERVER_ID_START) {
 | 
						if (i < WL_SERVER_ID_START) {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_CLIENT_SIDE)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->client_entries;
 | 
							entries = &map->client_entries;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_SERVER_SIDE)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->server_entries;
 | 
							entries = &map->server_entries;
 | 
				
			||||||
		i -= WL_SERVER_ID_START;
 | 
							i -= WL_SERVER_ID_START;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -262,8 +275,14 @@ wl_map_remove(struct wl_map *map, uint32_t i)
 | 
				
			||||||
	struct wl_array *entries;
 | 
						struct wl_array *entries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < WL_SERVER_ID_START) {
 | 
						if (i < WL_SERVER_ID_START) {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_SERVER_SIDE)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->client_entries;
 | 
							entries = &map->client_entries;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							if (map->side == WL_MAP_CLIENT_SIDE)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries = &map->server_entries;
 | 
							entries = &map->server_entries;
 | 
				
			||||||
		i -= WL_SERVER_ID_START;
 | 
							i -= WL_SERVER_ID_START;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue