aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore/xenstored_core.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-05-01 10:00:00 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-05-01 10:00:00 +0100
commit84aaf4530b7d495668fb2c69fdd6f5c28533c1ac (patch)
treecb246156ea962092bef37df767ef8fbaeeba043f /tools/xenstore/xenstored_core.c
parenta2f23ae851a744beb582ab4f11d654516fde1e78 (diff)
downloadxen-84aaf4530b7d495668fb2c69fdd6f5c28533c1ac.tar.gz
xen-84aaf4530b7d495668fb2c69fdd6f5c28533c1ac.tar.bz2
xen-84aaf4530b7d495668fb2c69fdd6f5c28533c1ac.zip
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>
Diffstat (limited to 'tools/xenstore/xenstored_core.c')
-rw-r--r--tools/xenstore/xenstored_core.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 657322ab8c..b391319a15 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -1929,7 +1929,7 @@ int main(int argc, char *argv[])
/* Main loop. */
for (;;) {
- struct connection *conn, *old_conn;
+ struct connection *conn, *next;
if (select(max+1, &inset, &outset, NULL, timeout) < 0) {
if (errno == EINTR)
@@ -1953,27 +1953,39 @@ int main(int argc, char *argv[])
if (evtchn_fd != -1 && FD_ISSET(evtchn_fd, &inset))
handle_event();
- conn = list_entry(connections.next, typeof(*conn), list);
- while (&conn->list != &connections) {
- talloc_increase_ref_count(conn);
+ next = list_entry(connections.next, typeof(*conn), list);
+ while (&next->list != &connections) {
+ conn = next;
+
+ next = list_entry(conn->list.next,
+ typeof(*conn), list);
if (conn->domain) {
+ talloc_increase_ref_count(conn);
if (domain_can_read(conn))
handle_input(conn);
+ if (talloc_free(conn) == 0)
+ continue;
+
+ talloc_increase_ref_count(conn);
if (domain_can_write(conn) &&
!list_empty(&conn->out_list))
handle_output(conn);
+ if (talloc_free(conn) == 0)
+ continue;
} else {
+ talloc_increase_ref_count(conn);
if (FD_ISSET(conn->fd, &inset))
handle_input(conn);
+ if (talloc_free(conn) == 0)
+ continue;
+
+ talloc_increase_ref_count(conn);
if (FD_ISSET(conn->fd, &outset))
handle_output(conn);
+ if (talloc_free(conn) == 0)
+ continue;
}
-
- old_conn = conn;
- conn = list_entry(old_conn->list.next,
- typeof(*conn), list);
- talloc_free(old_conn);
}
max = initialize_set(&inset, &outset, *sock, *ro_sock,