httpd running with fastcgi leaks the file descriptor if it opens the
socket but fails to connect it. Can be demonstrated by starting httpd
with a fastcgi config, opening a silly amount of sockets and throwing a
bunch of requests at it (eg. with apache bench) so the connections fail.


$ fstat | grep httpd | wc -l      
      57
$ ab -n 10000 -c 500 http://127.0.0.1/fcgitest/
$ grep 'Connection refused' /var/www/logs/error.log | wc -l 
    4540

4540 + 57 is...

$ fstat | grep httpd | wc -l                                
    4597

If clt_fd is already set to fd, it will be closed when
server_abort_http() calls server_close() which calls close(), but
if fail happened before it was set, fd needs to be closed here.


Index: usr.sbin/httpd/server_fcgi.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_fcgi.c,v
retrieving revision 1.64
diff -u -p -u -r1.64 server_fcgi.c
--- usr.sbin/httpd/server_fcgi.c        20 Aug 2015 13:00:23 -0000      1.64
+++ usr.sbin/httpd/server_fcgi.c        7 Oct 2015 11:49:30 -0000
@@ -399,6 +399,8 @@ server_fcgi(struct httpd *env, struct cl
        free(script);
        if (errstr == NULL)
                errstr = strerror(errno);
+       if (fd != -1 && clt->clt_fd != fd)
+               close(fd);
        server_abort_http(clt, 500, errstr);
        return (-1);
 }


Also, a small grammatical fix:

Index: usr.sbin/httpd/server_fcgi.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_fcgi.c,v
retrieving revision 1.64
diff -u -p -u -r1.64 server_fcgi.c
--- usr.sbin/httpd/server_fcgi.c        20 Aug 2015 13:00:23 -0000      1.64
+++ usr.sbin/httpd/server_fcgi.c        7 Oct 2015 11:49:01 -0000
@@ -130,7 +130,7 @@ server_fcgi(struct httpd *env, struct cl
                len = strlcpy(sun.sun_path,
                    srv_conf->socket, sizeof(sun.sun_path));
                if (len >= sizeof(sun.sun_path)) {
-                       errstr = "socket path to long";
+                       errstr = "socket path too long";
                        goto fail;
                }
                sun.sun_len = len;

-- 
Carlin

Reply via email to