ia64/xen-unstable

changeset 17539:5e5bc5b2bb6d

xemnstored: Fix xenstored abort when connection dropped.

If a connection is dropped with pending input and output data then the
connection will be dereferenced by both handle_input and handle_output
resulting in a double free when the main loop dereferences the
connection.

Fix this issue by taking/releasing a reference over the calls to
handle_input and handle_output separately and checking the result of
talloc_free to see if the connection went away.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 01 10:00:00 2008 +0100 (2008-05-01)
parents 2cf9a8736bab
children 8bced3d8a907
files tools/xenstore/xenstored_core.c
line diff
     1.1 --- a/tools/xenstore/xenstored_core.c	Thu May 01 09:55:45 2008 +0100
     1.2 +++ b/tools/xenstore/xenstored_core.c	Thu May 01 10:00:00 2008 +0100
     1.3 @@ -1929,7 +1929,7 @@ int main(int argc, char *argv[])
     1.4  
     1.5  	/* Main loop. */
     1.6  	for (;;) {
     1.7 -		struct connection *conn, *old_conn;
     1.8 +		struct connection *conn, *next;
     1.9  
    1.10  		if (select(max+1, &inset, &outset, NULL, timeout) < 0) {
    1.11  			if (errno == EINTR)
    1.12 @@ -1953,27 +1953,39 @@ int main(int argc, char *argv[])
    1.13  		if (evtchn_fd != -1 && FD_ISSET(evtchn_fd, &inset))
    1.14  			handle_event();
    1.15  
    1.16 -		conn = list_entry(connections.next, typeof(*conn), list);
    1.17 -		while (&conn->list != &connections) {
    1.18 -			talloc_increase_ref_count(conn);
    1.19 +		next = list_entry(connections.next, typeof(*conn), list);
    1.20 +		while (&next->list != &connections) {
    1.21 +			conn = next;
    1.22 +
    1.23 +			next = list_entry(conn->list.next,
    1.24 +					  typeof(*conn), list);
    1.25  
    1.26  			if (conn->domain) {
    1.27 +				talloc_increase_ref_count(conn);
    1.28  				if (domain_can_read(conn))
    1.29  					handle_input(conn);
    1.30 +				if (talloc_free(conn) == 0)
    1.31 +					continue;
    1.32 +
    1.33 +				talloc_increase_ref_count(conn);
    1.34  				if (domain_can_write(conn) &&
    1.35  				    !list_empty(&conn->out_list))
    1.36  					handle_output(conn);
    1.37 +				if (talloc_free(conn) == 0)
    1.38 +					continue;
    1.39  			} else {
    1.40 +				talloc_increase_ref_count(conn);
    1.41  				if (FD_ISSET(conn->fd, &inset))
    1.42  					handle_input(conn);
    1.43 +				if (talloc_free(conn) == 0)
    1.44 +					continue;
    1.45 +
    1.46 +				talloc_increase_ref_count(conn);
    1.47  				if (FD_ISSET(conn->fd, &outset))
    1.48  					handle_output(conn);
    1.49 +				if (talloc_free(conn) == 0)
    1.50 +					continue;
    1.51  			}
    1.52 -
    1.53 -			old_conn = conn;
    1.54 -			conn = list_entry(old_conn->list.next,
    1.55 -					  typeof(*conn), list);
    1.56 -			talloc_free(old_conn);
    1.57  		}
    1.58  
    1.59  		max = initialize_set(&inset, &outset, *sock, *ro_sock,