nbd: Fully initialize client in case of failed negotiation
If a non-NBD client connects to qemu-nbd, we would end up with a SIGSEGV in nbd_client_put() because we were trying to unregister the client's association to the export, even though we skipped inserting the client into that list. Easy trigger in two terminals: $ qemu-nbd -p 30001 --format=raw file $ nmap 127.0.0.1 -p 30001 nmap claims that it thinks it connected to a pago-services1 server (which probably means nmap could be updated to learn the NBD protocol and give a more accurate diagnosis of the open port - but that's not our problem), then terminates immediately, so our call to nbd_negotiate() fails. The fix is to reorder nbd_co_client_start() to ensure that all initialization occurs before we ever try talking to a client in nbd_negotiate(), so that the teardown sequence on negotiation failure doesn't fault while dereferencing a half-initialized object. While debugging this, I also noticed that nbd_update_server_watch() called by nbd_client_closed() was still adding a channel to accept the next client, even when the state was no longer RUNNING. That is fixed by making nbd_can_accept() pay attention to the current state. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614 Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20170527030421.28366-1-eblake@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									ad9579aaa1
								
							
						
					
					
						commit
						df8ad9f128
					
				
							
								
								
									
										10
									
								
								nbd/server.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								nbd/server.c
									
									
									
									
									
								
							| @ -1358,15 +1358,13 @@ static coroutine_fn void nbd_co_client_start(void *opaque) | ||||
| 
 | ||||
|     if (exp) { | ||||
|         nbd_export_get(exp); | ||||
|     } | ||||
|     if (nbd_negotiate(data)) { | ||||
|         client_close(client); | ||||
|         goto out; | ||||
|         QTAILQ_INSERT_TAIL(&exp->clients, client, next); | ||||
|     } | ||||
|     qemu_co_mutex_init(&client->send_lock); | ||||
| 
 | ||||
|     if (exp) { | ||||
|         QTAILQ_INSERT_TAIL(&exp->clients, client, next); | ||||
|     if (nbd_negotiate(data)) { | ||||
|         client_close(client); | ||||
|         goto out; | ||||
|     } | ||||
| 
 | ||||
|     nbd_client_receive_next_request(client); | ||||
|  | ||||
| @ -325,7 +325,7 @@ out: | ||||
| 
 | ||||
| static int nbd_can_accept(void) | ||||
| { | ||||
|     return nb_fds < shared; | ||||
|     return state == RUNNING && nb_fds < shared; | ||||
| } | ||||
| 
 | ||||
| static void nbd_export_closed(NBDExport *exp) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Eric Blake
						Eric Blake