ia64/xen-unstable

changeset 6204:2c2015c11b49

Under the right circumstances, xenconsoled will corrupt its internal
list of domains causing a SEGV. This is usually characterized by a
rapid number of creations/destructions. The attached patch fixes this.

1) Fix uninitialized next pointer. This could sometimes cause xenconsoled to
SEGV on an invalid domain pointer
2) Fix race condition in iterating domain list where removing a domain in a
callback could lead to the iterators becoming invalid.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 16 07:06:10 2005 +0000 (2005-08-16)
parents 60d20acf8928
children 0237746ecf92
files tools/console/daemon/io.c
line diff
     1.1 --- a/tools/console/daemon/io.c	Tue Aug 16 01:04:32 2005 +0000
     1.2 +++ b/tools/console/daemon/io.c	Tue Aug 16 07:06:10 2005 +0000
     1.3 @@ -87,6 +87,7 @@ struct domain
     1.4  {
     1.5  	int domid;
     1.6  	int tty_fd;
     1.7 +	bool is_dead;
     1.8  	struct buffer buffer;
     1.9  	struct domain *next;
    1.10  };
    1.11 @@ -156,10 +157,12 @@ static struct domain *create_domain(int 
    1.12  
    1.13  	dom->domid = domid;
    1.14  	dom->tty_fd = domain_create_tty(dom);
    1.15 +	dom->is_dead = false;
    1.16  	dom->buffer.data = 0;
    1.17  	dom->buffer.size = 0;
    1.18  	dom->buffer.capacity = 0;
    1.19  	dom->buffer.max_capacity = 0;
    1.20 +	dom->next = 0;
    1.21  
    1.22  	dolog(LOG_DEBUG, "New domain %d", domid);
    1.23  
    1.24 @@ -206,6 +209,16 @@ static void remove_domain(struct domain 
    1.25  	}
    1.26  }
    1.27  
    1.28 +static void remove_dead_domains(struct domain *dom)
    1.29 +{
    1.30 +	if (dom == NULL) return;
    1.31 +	remove_dead_domains(dom->next);
    1.32 +
    1.33 +	if (dom->is_dead) {
    1.34 +		remove_domain(dom);
    1.35 +	}
    1.36 +}
    1.37 +
    1.38  static void handle_tty_read(struct domain *dom)
    1.39  {
    1.40  	ssize_t len;
    1.41 @@ -224,7 +237,7 @@ static void handle_tty_read(struct domai
    1.42  		if (domain_is_valid(dom->domid)) {
    1.43  			dom->tty_fd = domain_create_tty(dom);
    1.44  		} else {
    1.45 -			remove_domain(dom);
    1.46 +			dom->is_dead = true;
    1.47  		}
    1.48  	} else if (domain_is_valid(dom->domid)) {
    1.49  		msg.u.control.msg.length = len;
    1.50 @@ -235,7 +248,7 @@ static void handle_tty_read(struct domai
    1.51  		}
    1.52  	} else {
    1.53  		close(dom->tty_fd);
    1.54 -		remove_domain(dom);
    1.55 +		dom->is_dead = true;
    1.56  	}
    1.57  }
    1.58  
    1.59 @@ -250,7 +263,7 @@ static void handle_tty_write(struct doma
    1.60  		if (domain_is_valid(dom->domid)) {
    1.61  			dom->tty_fd = domain_create_tty(dom);
    1.62  		} else {
    1.63 -			remove_domain(dom);
    1.64 +			dom->is_dead = true;
    1.65  		}
    1.66  	} else {
    1.67  		buffer_advance(&dom->buffer, len);
    1.68 @@ -333,13 +346,15 @@ void handle_io(void)
    1.69  		}
    1.70  
    1.71  		for (d = dom_head; d; d = d->next) {
    1.72 -			if (FD_ISSET(d->tty_fd, &readfds)) {
    1.73 +			if (!d->is_dead && FD_ISSET(d->tty_fd, &readfds)) {
    1.74  				handle_tty_read(d);
    1.75  			}
    1.76  
    1.77 -			if (FD_ISSET(d->tty_fd, &writefds)) {
    1.78 +			if (!d->is_dead && FD_ISSET(d->tty_fd, &writefds)) {
    1.79  				handle_tty_write(d);
    1.80  			}
    1.81  		}
    1.82 +
    1.83 +		remove_dead_domains(dom_head);
    1.84  	} while (ret > -1);
    1.85  }