vhost: fix cleanup on not fully initialized device
If vhost_dev_init() failed, caller may still call vhost_dev_cleanup() later. However, vhost_dev_cleanup() tries to remove the device from the list even if it wasn't yet added, which may lead to crashes. Similarly for the memory listener. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									7b527247f0
								
							
						
					
					
						commit
						5be5f9be72
					
				| @ -1033,7 +1033,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, | |||||||
|         r = -1; |         r = -1; | ||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
|     QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); |  | ||||||
| 
 | 
 | ||||||
|     r = hdev->vhost_ops->vhost_set_owner(hdev); |     r = hdev->vhost_ops->vhost_set_owner(hdev); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
| @ -1103,6 +1102,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, | |||||||
|     hdev->started = false; |     hdev->started = false; | ||||||
|     hdev->memory_changed = false; |     hdev->memory_changed = false; | ||||||
|     memory_listener_register(&hdev->memory_listener, &address_space_memory); |     memory_listener_register(&hdev->memory_listener, &address_space_memory); | ||||||
|  |     QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); | ||||||
|     return 0; |     return 0; | ||||||
| fail_busyloop: | fail_busyloop: | ||||||
|     while (--i >= 0) { |     while (--i >= 0) { | ||||||
| @ -1126,7 +1126,11 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) | |||||||
|     for (i = 0; i < hdev->nvqs; ++i) { |     for (i = 0; i < hdev->nvqs; ++i) { | ||||||
|         vhost_virtqueue_cleanup(hdev->vqs + i); |         vhost_virtqueue_cleanup(hdev->vqs + i); | ||||||
|     } |     } | ||||||
|     memory_listener_unregister(&hdev->memory_listener); |     if (hdev->mem) { | ||||||
|  |         /* those are only safe after successful init */ | ||||||
|  |         memory_listener_unregister(&hdev->memory_listener); | ||||||
|  |         QLIST_REMOVE(hdev, entry); | ||||||
|  |     } | ||||||
|     if (hdev->migration_blocker) { |     if (hdev->migration_blocker) { | ||||||
|         migrate_del_blocker(hdev->migration_blocker); |         migrate_del_blocker(hdev->migration_blocker); | ||||||
|         error_free(hdev->migration_blocker); |         error_free(hdev->migration_blocker); | ||||||
| @ -1135,7 +1139,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) | |||||||
|     g_free(hdev->mem_sections); |     g_free(hdev->mem_sections); | ||||||
|     hdev->vhost_ops->vhost_backend_cleanup(hdev); |     hdev->vhost_ops->vhost_backend_cleanup(hdev); | ||||||
|     assert(!hdev->log); |     assert(!hdev->log); | ||||||
|     QLIST_REMOVE(hdev, entry); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Stop processing guest IO notifications in qemu.
 | /* Stop processing guest IO notifications in qemu.
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Marc-André Lureau
						Marc-André Lureau