[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] xenconsoled: use array index to keep track of pollfd



On 19/03/13 17:45, Wei Liu wrote:
If we use pointers to reference elements inside array, it is possible that we
get wild pointer after realloc(3) copies array and returns a new pointer.

Keep track of element indexes inside the array can solve this problem.

Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: Marcus Granado <marcus.granado@xxxxxxxxxx>
---
  tools/console/daemon/io.c |   66 ++++++++++++++++++++++++---------------------
  1 file changed, 35 insertions(+), 31 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 50f91b5..250550a 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -87,7 +87,7 @@ struct buffer {
  struct domain {
        int domid;
        int master_fd;
-       struct pollfd *master_pollfd;
+       int master_pollfd_idx;
        int slave_fd;
        int log_fd;
        bool is_dead;
@@ -99,7 +99,7 @@ struct domain {
        evtchn_port_or_error_t local_port;
        evtchn_port_or_error_t remote_port;
        xc_evtchn *xce_handle;
-       struct pollfd *xce_pollfd;
+       int xce_pollfd_idx;
        struct xencons_interface *interface;
        int event_count;
        long long next_period;
@@ -669,8 +669,10 @@ static struct domain *create_domain(int domid)
        strcat(dom->conspath, "/console");

        dom->master_fd = -1;
+       dom->master_pollfd_idx = -1;
        dom->slave_fd = -1;
        dom->log_fd = -1;
+       dom->xce_pollfd_idx = -1;

        dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 
1000000) + RATE_LIMIT_PERIOD;

@@ -944,9 +946,10 @@ static void handle_log_reload(void)
        }
  }

-static struct pollfd *set_fds(int fd, short events)
+/* Returns index inside fds array if succees, -1 if fail */
+static int set_fds(int fd, short events)
  {
-       struct pollfd *ret;
+       int ret;
        if (current_array_size < nr_fds + 1) {
                struct pollfd  *new_fds = NULL;
                unsigned long newsize;
@@ -968,27 +971,28 @@ static struct pollfd *set_fds(int fd, short events)

        fds[nr_fds].fd = fd;
        fds[nr_fds].events = events;
-       ret = &fds[nr_fds];
+       ret = nr_fds;
        nr_fds++;

        return ret;
  fail:
        dolog(LOG_ERR, "realloc failed, ignoring fd %d\n", fd);
-       return NULL;
+       return -1;
  }

  static void reset_fds(void)
  {
        nr_fds = 0;
-       memset(fds, 0, sizeof(struct pollfd) * current_array_size);
+       if (fds)
+               memset(fds, 0, sizeof(struct pollfd) * current_array_size);
  }

  void handle_io(void)
  {
        int ret;
        evtchn_port_or_error_t log_hv_evtchn = -1;
-       struct pollfd *xce_pollfd = NULL;
-       struct pollfd *xs_pollfd = NULL;
+       int xce_pollfd_idx = -1;
+       int xs_pollfd_idx = -1;
        xc_evtchn *xce_handle = NULL;

        if (log_hv) {
@@ -1025,11 +1029,11 @@ void handle_io(void)

                reset_fds();

-               xs_pollfd = set_fds(xs_fileno(xs), POLLIN|POLLPRI);
+               xs_pollfd_idx = set_fds(xs_fileno(xs), POLLIN|POLLPRI);

                if (log_hv)
-                       xce_pollfd = set_fds(xc_evtchn_fd(xce_handle),
-                                            POLLIN|POLLPRI);
+                       xce_pollfd_idx = set_fds(xc_evtchn_fd(xce_handle),
+                                                POLLIN|POLLPRI);

                if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
                        return;
@@ -1064,8 +1068,8 @@ void handle_io(void)
                                    !d->buffer.max_capacity ||
                                    d->buffer.size < d->buffer.max_capacity) {
                                        int evtchn_fd = 
xc_evtchn_fd(d->xce_handle);
-                                       d->xce_pollfd = set_fds(evtchn_fd,
-                                                               POLLIN|POLLPRI);
+                                       d->xce_pollfd_idx = set_fds(evtchn_fd,
+                                                                   
POLLIN|POLLPRI);
                                }
                        }

@@ -1078,7 +1082,7 @@ void handle_io(void)
                                        events |= POLLOUT;

                                if (events)
-                                       d->master_pollfd =
+                                       d->master_pollfd_idx =
                                                set_fds(d->master_fd,
                                                        events|POLLPRI);
                        }
@@ -1110,61 +1114,61 @@ void handle_io(void)
                        break;
                }

-               if (log_hv && xce_pollfd) {
-                       if (xce_pollfd->revents & ~(POLLIN|POLLOUT|POLLPRI)) {
+               if (log_hv && xce_pollfd_idx != -1) {
+                       if (fds[xce_pollfd_idx].revents & 
~(POLLIN|POLLOUT|POLLPRI)) {
                                dolog(LOG_ERR,
                                      "Failure in poll xce_handle: %d (%s)",
                                      errno, strerror(errno));
                                break;
-                       } else if (xce_pollfd->revents & POLLIN)
+                       } else if (fds[xce_pollfd_idx].revents & POLLIN)
                                handle_hv_logs(xce_handle);

-                       xce_pollfd = NULL;
+                       xce_pollfd_idx = -1;
                }

                if (ret <= 0)
                        continue;

-               if (xs_pollfd) {
-                       if (xs_pollfd->revents & ~(POLLIN|POLLOUT|POLLPRI)) {
+               if (xs_pollfd_idx != -1) {
+                       if (fds[xs_pollfd_idx].revents & 
~(POLLIN|POLLOUT|POLLPRI)) {
                                dolog(LOG_ERR,
                                      "Failure in poll xs_handle: %d (%s)",
                                      errno, strerror(errno));
                                break;
-                       } else if (xs_pollfd->revents & POLLIN)
+                       } else if (fds[xs_pollfd_idx].revents & POLLIN)
                                handle_xs();

-                       xs_pollfd = NULL;
+                       xs_pollfd_idx = -1;
                }

                for (d = dom_head; d; d = n) {
                        n = d->next;
                        if (d->event_count < RATE_LIMIT_ALLOWANCE) {
                                if (d->xce_handle != NULL &&
-                                   d->xce_pollfd &&
-                                   !(d->xce_pollfd->revents &
+                                   d->xce_pollfd_idx != -1 &&
+                                   !(fds[d->xce_pollfd_idx].revents &
                                      ~(POLLIN|POLLOUT|POLLPRI)) &&
-                                     (d->xce_pollfd->revents &
+                                     (fds[d->xce_pollfd_idx].revents &
                                       POLLIN))
                                    handle_ring_read(d);
                        }

-                       if (d->master_fd != -1 && d->master_pollfd) {
-                               if (d->master_pollfd->revents &
+                       if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
+                               if (fds[d->master_pollfd_idx].revents &
                                    ~(POLLIN|POLLOUT|POLLPRI))
                                        domain_handle_broken_tty(d,
                                                   domain_is_valid(d->domid));
                                else {
-                                       if (d->master_pollfd->revents &
+                                       if (fds[d->master_pollfd_idx].revents &
                                            POLLIN)
                                                handle_tty_read(d);
-                                       if (d->master_pollfd->revents &
+                                       if (fds[d->master_pollfd_idx].revents &
                                            POLLOUT)
                                                handle_tty_write(d);
                                }
                        }

-                       d->xce_pollfd = d->master_pollfd = NULL;
+                       d->xce_pollfd_idx = d->master_pollfd_idx = -1;

                        if (d->last_seen != enum_pass)
                                shutdown_domain(d);


I was able to start 700 vms in a host using the patch above.

Reviewed-by: Marcus Granado <marcus.granado@xxxxxxxxxx>
Tested-by: Marcus Granado <marcus.granado@xxxxxxxxxx>



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.