]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: listeners: CLOEXEC flag is not correctly set
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 27 Nov 2018 11:02:39 +0000 (12:02 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 27 Nov 2018 18:34:00 +0000 (19:34 +0100)
The CLOEXEC flag was set using a F_SETFL which can't work.
To set the CLOEXEC flag F_SETFD should be used, the problem is that it
needs a new call to fcntl() and it's on the path of every accept.

This flag was only needed in the case of the master, so the patch was
reverted and the flag set only in this case.

The bug was introduced by 0b3e849 ("MEDIUM: listeners: set O_CLOEXEC on
the accepted FDs").

No backport needed.

src/listener.c

index c75f8ef719ec680a4ff151198799900c7313f7d7..37466d44ecaa81ac396bd3847af1958e659d5074 100644 (file)
@@ -544,7 +544,7 @@ void listener_accept(int fd)
                /* with sockpair@ we don't want to do an accept */
                if (unlikely(l->addr.ss_family == AF_CUST_SOCKPAIR)) {
                        if ((cfd = recv_fd_uxst(fd)) != -1)
-                               fcntl(cfd, F_SETFL, O_NONBLOCK|O_CLOEXEC);
+                               fcntl(cfd, F_SETFL, O_NONBLOCK);
                } else
 
 #ifdef USE_ACCEPT4
@@ -552,12 +552,12 @@ void listener_accept(int fd)
                 * fallback to the legacy accept() + fcntl().
                 */
                if (unlikely(accept4_broken ||
-                       ((cfd = accept4(fd, (struct sockaddr *)&addr, &laddr, SOCK_NONBLOCK|SOCK_CLOEXEC)) == -1 &&
+                       ((cfd = accept4(fd, (struct sockaddr *)&addr, &laddr, SOCK_NONBLOCK)) == -1 &&
                        (errno == ENOSYS || errno == EINVAL || errno == EBADF) &&
                        (accept4_broken = 1))))
 #endif
                        if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) != -1)
-                               fcntl(cfd, F_SETFL, O_NONBLOCK|O_CLOEXEC);
+                               fcntl(cfd, F_SETFL, O_NONBLOCK);
 
                if (unlikely(cfd == -1)) {
                        switch (errno) {
@@ -604,6 +604,10 @@ void listener_accept(int fd)
                        }
                }
 
+               /* we don't want to leak the FD upon reload if it's in the master */
+               if (unlikely(master == 1))
+                       fcntl(cfd, F_SETFD, FD_CLOEXEC);
+
                if (unlikely(cfd >= global.maxsock)) {
                        send_log(p, LOG_EMERG,
                                 "Proxy %s reached the configured maximum connection limit. Please check the global 'maxconn' value.\n",