Bug 47335

Summary: An extra stderr file descriptor is leaked to forked CGI processes
Product: Apache httpd-2 Reporter: Kornél Pál <kornelpal>
Component: mod_cgiAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: RESOLVED FIXED    
Severity: normal Keywords: FixedInTrunk
Priority: P2    
Version: 2.2.11   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Attachments: mod_cgid.diff

Description Kornél Pál 2009-06-09 05:41:35 UTC
I've found this bug on a production server and created a test environment using httpd-2.2.11.tar.bz2 with default configuration settings. Both systems present the bug.

Test CGI script:
#!/bin/bash
echo "Content-Type: text/plain"
echo ""
ls -laR /proc/$$/fd 

Executing from shell:
Content-Type: text/plain

/proc/15922/fd:
total 0
dr-x------ 2 root root  0 Jun  9 14:37 .
dr-xr-xr-x 5 root root  0 Jun  9 14:37 ..
lrwx------ 1 root root 64 Jun  9 14:37 0 -> /dev/pts/2
lrwx------ 1 root root 64 Jun  9 14:37 1 -> /dev/pts/2
lrwx------ 1 root root 64 Jun  9 14:37 2 -> /dev/pts/2
lr-x------ 1 root root 64 Jun  9 14:37 255 -> /root/httpd/cgi-bin/leak.cgi

Executing from Apache:
/proc/15963/fd:
total 0
dr-x------ 2 daemon daemon  0 Jun  9 14:38 .
dr-xr-xr-x 5 daemon daemon  0 Jun  9 14:38 ..
lr-x------ 1 daemon daemon 64 Jun  9 14:38 0 -> pipe:[85321]
l-wx------ 1 daemon daemon 64 Jun  9 14:38 1 -> pipe:[85322]
lr-x------ 1 daemon daemon 64 Jun  9 14:38 14 -> pipe:[85323]
l-wx------ 1 daemon daemon 64 Jun  9 14:38 2 -> pipe:[85323]
lr-x------ 1 daemon daemon 64 Jun  9 14:38 255 -> /root/httpd/cgi-bin/leak.cgi

File descriptor 14 is a copy of stderr. 14 is used for subsequent requests as well with the actual stderr. This number was significantly higher on the production system but was still constant.
Comment 1 Rainer Jung 2009-06-09 07:09:23 UTC
So is it only one additional FD during operation, or does the number of additional FDs increase due to traffic or Apache restarts?
Comment 2 Kornél Pál 2009-06-09 07:16:00 UTC
There is only one extra fd that always points to the actual stderr used for the process. The fd value (14 in the report) appears to be the same in subsequent requests (haven't do stress test) even through different stderr pipes are used.
Comment 3 Kornél Pál 2009-06-09 07:21:55 UTC
Results of two subsequent requests from the production server (using suexec but the bug is the same):

/proc/12138/fd:
total 0
dr-x------ 2 username username  0 Jun  9 09:19 .
dr-xr-xr-x 5 username username  0 Jun  9 09:19 ..
lr-x------ 1 username username 64 Jun  9 09:19 0 -> pipe:[155152349]
l-wx------ 1 username username 64 Jun  9 09:19 1 -> pipe:[155152350]
l-wx------ 1 username username 64 Jun  9 09:19 2 -> pipe:[155152351]
lr-x------ 1 username username 64 Jun  9 09:19 255 -> /home/username/public_html/cgi-bin/leak.cgi
lr-x------ 1 username username 64 Jun  9 09:19 3483 -> pipe:[155152351]


/proc/12275/fd:
total 0
dr-x------ 2 username username  0 Jun  9 09:19 .
dr-xr-xr-x 5 username username  0 Jun  9 09:19 ..
lr-x------ 1 username username 64 Jun  9 09:19 0 -> pipe:[155153317]
l-wx------ 1 username username 64 Jun  9 09:19 1 -> pipe:[155153318]
l-wx------ 1 username username 64 Jun  9 09:19 2 -> pipe:[155153319]
lr-x------ 1 username username 64 Jun  9 09:19 255 -> /home/username/public_html/cgi-bin/leak.cgi
lr-x------ 1 username username 64 Jun  9 09:19 3483 -> pipe:[155153319]
Comment 4 Ruediger Pluem 2009-06-09 08:55:03 UTC
As one can see fd14 is actually the reading site of the stderr pipe:

lr-x------ 1 daemon daemon 64 Jun  9 14:38 14 -> pipe:[85323]
l-wx------ 1 daemon daemon 64 Jun  9 14:38 2 -> pipe:[85323]

Some questions:

Which MPM are you using?
Which cgi module are you using (mod_cgi or mod_cgid)?
Comment 5 Kornél Pál 2009-06-09 10:10:01 UTC
prefork
mod_cgi
Apache 2.2.11
CentOS 5.3 x86_64
Comment 6 Kornél Pál 2009-06-09 10:59:08 UTC
I've tried with worker and mod_cgid and the leakage is present:

/proc/10380/fd:
total 0
dr-x------ 2 daemon daemon  0 Jun  9 19:54 .
dr-xr-xr-x 5 daemon daemon  0 Jun  9 19:54 ..
lrwx------ 1 daemon daemon 64 Jun  9 19:54 0 -> socket:[72840]
lrwx------ 1 daemon daemon 64 Jun  9 19:54 1 -> socket:[72840]
lr-x------ 1 daemon daemon 64 Jun  9 19:54 13 -> pipe:[72901]
l-wx------ 1 daemon daemon 64 Jun  9 19:54 2 -> /root/httpd/logs/error_log
lr-x------ 1 daemon daemon 64 Jun  9 19:54 255 -> /root/httpd/cgi-bin/leak.cgi
lrwx------ 1 daemon daemon 64 Jun  9 19:54 3 -> socket:[68357]


/proc/10407/fd:
total 0
dr-x------ 2 daemon daemon  0 Jun  9 19:54 .
dr-xr-xr-x 5 daemon daemon  0 Jun  9 19:54 ..
lrwx------ 1 daemon daemon 64 Jun  9 19:54 0 -> socket:[73024]
lrwx------ 1 daemon daemon 64 Jun  9 19:54 1 -> socket:[73024]
lr-x------ 1 daemon daemon 64 Jun  9 19:54 13 -> pipe:[73028]
l-wx------ 1 daemon daemon 64 Jun  9 19:54 2 -> /root/httpd/logs/error_log
lr-x------ 1 daemon daemon 64 Jun  9 19:54 255 -> /root/httpd/cgi-bin/leak.cgi
lrwx------ 1 daemon daemon 64 Jun  9 19:54 3 -> socket:[68357]


fd 13 is a read pipe here as well and is a different pipe for each request just like with mod_cgi.

Also note that fd 3 seems to be leaking as well.
Comment 7 Ruediger Pluem 2009-06-10 01:18:18 UTC
Can you please check if the following patch fixes your issue?

Index: threadproc/unix/proc.c
===================================================================
--- threadproc/unix/proc.c      (revision 783248)
+++ threadproc/unix/proc.c      (working copy)
@@ -78,7 +78,7 @@

     if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
         if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
-                                          err, attr->pool)) != APR_SUCCESS)
+                                          err, attr->pool)) == APR_SUCCESS)
             rv = apr_file_inherit_unset(attr->parent_err);
         if (rv != APR_SUCCESS)
             return rv;
Comment 8 Kornél Pál 2009-06-10 04:55:19 UTC
Created attachment 23784 [details]
mod_cgid.diff

Thanks for the patch. This fixed pipe leak for me both with mod_cgi and mod_cgid.

Note that this fixed test seems to bogus on other plaforms as well.

mod_cgid is also leaking an extra listener socket fd (as described in Comment #6) that can be fixed with the attached patch but I don't know if it is compatible with APR_HAS_OTHER_CHILD.
Comment 9 Ruediger Pluem 2009-06-10 08:49:26 UTC
Fixed the apr issue in r783398 and backported it to 1.3.x / 1.4.x.
Comment 10 Kornél Pál 2009-06-10 09:05:33 UTC
Thanks. Note that beos, netware and os2 proc.c files have exactly the same bug. (exactly the same piece of code)
Comment 11 Ruediger Pluem 2009-06-11 05:20:58 UTC
(In reply to comment #10)
> Thanks. Note that beos, netware and os2 proc.c files have exactly the same bug.
> (exactly the same piece of code)

Thanks for the hint. This is now fixed.
Comment 12 Ruediger Pluem 2009-06-11 05:36:51 UTC
(In reply to comment #8)
> Created an attachment (id=23784) [details]
> mod_cgid.diff
> 
> Thanks for the patch. This fixed pipe leak for me both with mod_cgi and
> mod_cgid.
> 
> Note that this fixed test seems to bogus on other plaforms as well.
> 
> mod_cgid is also leaking an extra listener socket fd (as described in Comment
> #6) that can be fixed with the attached patch but I don't know if it is
> compatible with APR_HAS_OTHER_CHILD.

Thanks for the patch. Committed to trunk in r783740 and r783742.
Comment 13 Kornél Pál 2009-06-11 05:43:31 UTC
Thanks.
Comment 14 Stefan Fritsch 2012-02-26 16:56:09 UTC
fixed in 2.4.1