]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
* fixed a nasty bug in epoll_loop() and poll_loop() by which an EPOLL_HUP event
authorWilly TARREAU <willy@pcw.(none)>
Sun, 8 Jan 2006 00:24:12 +0000 (01:24 +0100)
committerWilly TARREAU <willy@pcw.(none)>
Sun, 8 Jan 2006 00:24:12 +0000 (01:24 +0100)
  could trigger both a read and a write calls, thus sometimes inducing headers
  being directly sent from srv to cli without modification, and leading further
  modification to crash the process by memory corruption, because
  rep.data+rep.l<rep.h so the memmove() length argument is negative. Only
  observed with epoll() and never poll(), though this one should have been
  affected too. Now, only call functions which have been allowed to.

haproxy.c

index a4fdd6f6f225edd895076a6033d5e785de3ed07e..6b634a900c4f76649e53f426dc62b2ab4ef58c73 100644 (file)
--- a/haproxy.c
+++ b/haproxy.c
@@ -2967,6 +2967,10 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, char *str, int len)
     if (delta + b->r >= b->data + BUFSIZE)
        return 0;  /* no space left */
 
+    if (b->data + b->l < end)
+       /* The data has been stolen, we could have crashed. Maybe we should abort() ? */
+       return 0;
+
     /* first, protect the end of the buffer */
     memmove(end + delta, end, b->data + b->l - end);
 
@@ -4194,7 +4198,10 @@ int process_srv(struct session *t) {
                    if (t->proxy->options & PR_O_COOK_NOC)
                        //len += sprintf(newhdr + len, "Cache-control: no-cache=\"set-cookie\"\r\n");
                        len += sprintf(trash + len, "Cache-control: private\r\n");
-                   
+
+                   if (rep->data + rep->l < rep->h)
+                       /* The data has been stolen, we will crash cleanly instead of corrupting memory */
+                       *(int *)0 = 0;
                    buffer_replace2(rep, rep->h, rep->h, trash, len);
                }
 
@@ -5354,14 +5361,18 @@ int epoll_loop(int action) {
          if (fdtab[fd].state == FD_STCLOSE)
              continue;
          
-         if (epoll_events[count].events & ( EPOLLIN | EPOLLERR | EPOLLHUP ))
-             fdtab[fd].read(fd);
+         if (epoll_events[count].events & ( EPOLLIN | EPOLLERR | EPOLLHUP )) {
+             if (FD_ISSET(fd, StaticReadEvent))
+                 fdtab[fd].read(fd);
+         }
          
          if (fdtab[fd].state == FD_STCLOSE)
              continue;
          
-         if (epoll_events[count].events & ( EPOLLOUT | EPOLLERR | EPOLLHUP ))
-             fdtab[fd].write(fd);
+         if (epoll_events[count].events & ( EPOLLOUT | EPOLLERR | EPOLLHUP )) {
+             if (FD_ISSET(fd, StaticWriteEvent))
+                 fdtab[fd].write(fd);
+         }
       }
   }
   return 1;
@@ -5475,14 +5486,18 @@ int poll_loop(int action) {
          if (fdtab[fd].state == FD_STCLOSE)
              continue;
          
-         if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP ))
-             fdtab[fd].read(fd);
+         if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP )) {
+             if (FD_ISSET(fd, StaticReadEvent))
+                 fdtab[fd].read(fd);
+         }
          
          if (fdtab[fd].state == FD_STCLOSE)
              continue;
          
-         if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP ))
-             fdtab[fd].write(fd);
+         if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP )) {
+             if (FD_ISSET(fd, StaticWriteEvent))
+                 fdtab[fd].write(fd);
+         }
       }
   }
   return 1;