* fixed a nasty bug in epoll_loop() and poll_loop() by which an EPOLL_HUP event
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.
diff --git a/haproxy.c b/haproxy.c
index a4fdd6f..6b634a9 100644
--- a/haproxy.c
+++ b/haproxy.c
@@ -2967,6 +2967,10 @@
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 @@
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 @@
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 @@
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;