On Wed, Dec 11, 2002 at 09:25:19AM -0500, Jim Jagielski wrote:
> This patch uses the recently folded in "magic" cleanups to
> have all log files (well, access and transfer logs) set with
> CLOSEXEC. It also adds another *_ex function (ap_popenf_ex)
> and allows for the magic cleanups to be called/run whenever
> by passing a NULL pool (also protects against dumps when
> a NULL might be passed by accident).
> 
> Comments??

I applied your patch in combination with my socket-fd patch,
and see for yourself:

 -> crw-rw-rw- 1 root     wheel       2,     2 /dev/fd/0
 -> p--------- 0 root     wheel              0 /dev/fd/1
 -> -rw-r----- 1 martin   kraemer         8812 /dev/fd/2 == /tmp/apa13/logs/error_log
 -> -rw-r----- 1 martin   kraemer         8812 /dev/fd/15 == /tmp/apa13/logs/error_log
 -> -rw------- 1 martin   kraemer            0 /dev/fd/19 == 
/tmp/apa13/logs/httpd.lock.30423
 -> -rw------- 1 martin   kraemer            0 /dev/fd/20 == 
/tmp/apa13/logs/httpd.lock.30423
 -> -rw-r----- 1 martin   kraemer          209 /dev/fd/21 == 
/tmp/apa13/htdocs/machine.php

In contrast to the patch in my previous reply (which called
ap_note_cleanups_for_fd_ex() for *ALL* occurrences of ap_popenf()),
we now have more open fd's in PHP again. The fd's of the fcntl() lock
files are (created by ap_popenf() and) not closed.
So, there's another potential for plugging fd's.
Other candidates are the scoreboard file (where present) which needs
not be inherited to children, the rewrite_log file, and mod_log_nw.c
for netware (do they have FD_CLOEXEC? I assume not... ;-) 

Basically, this leaves over only mod_mime_magic as a user for the non-_ex
version of ap_popenf(), and that is only because it does the open...close
in a tight loop which does not offer the possibility of a fork()/exec().

As could be expected, the combined patch with the additional invocations
of ap_popenf_ex() leaves open only the well known set of fds:

 -> crw-rw-rw- 1 root     wheel       2,     2 /dev/fd/0
 -> p--------- 0 root     wheel              0 /dev/fd/1
 -> -rw-r----- 1 martin   kraemer         9064 /dev/fd/2 == /tmp/apa13/logs/error_log
 -> -rw-r----- 1 martin   kraemer         9064 /dev/fd/15 == /tmp/apa13/logs/error_log
 -> -rw-r----- 1 martin   kraemer          209 /dev/fd/21 == 
/tmp/apa13/htdocs/machine.php

   Martin
PS: I append the combined patch of your changes and mine, but without
the new ap_psocket_ex(). TBD
-- 
<[EMAIL PROTECTED]>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1866
diff -u -r1.1866 CHANGES
--- CHANGES     9 Dec 2002 20:21:00 -0000       1.1866
+++ CHANGES     11 Dec 2002 16:13:04 -0000
@@ -1,5 +1,14 @@
 Changes with Apache 1.3.28
 
+  *) Certain 3rd party modules would bypass the Apache API and not
+     invoke ap_cleanup_for_exec() before creating sub-processes.
+     To such a child process, Apache's file descriptors (lock
+     fd's, log files, sockets) were accessible, allowing them
+     direct access to Apache log file etc.  Where the OS allows,
+     we now add proactive close functions to prevent these file
+     descriptors from leaking to the child processes.
+     [Jim Jagielski, Martin Kraemer]
+
   *) Prevent obscenely large values of precision in ap_vformatter
      from clobbering a buffer. [Sander Striker, Jim Jagielski]
 
Index: include/ap_alloc.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/ap_alloc.h,v
retrieving revision 1.80
diff -u -r1.80 ap_alloc.h
--- include/ap_alloc.h  8 Dec 2002 19:09:55 -0000       1.80
+++ include/ap_alloc.h  11 Dec 2002 16:13:04 -0000
@@ -337,6 +337,8 @@
 API_EXPORT(FILE *) ap_pfopen(struct pool *, const char *name, const char *fmode);
 API_EXPORT(FILE *) ap_pfdopen(struct pool *, int fd, const char *fmode);
 API_EXPORT(int) ap_popenf(struct pool *, const char *name, int flg, int mode);
+API_EXPORT(int) ap_popenf_ex(struct pool *, const char *name, int flg,
+                             int mode, int domagic);
 
 API_EXPORT(void) ap_note_cleanups_for_file(pool *, FILE *);
 API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *, FILE *, int);
Index: main/alloc.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/alloc.c,v
retrieving revision 1.134
diff -u -r1.134 alloc.c
--- main/alloc.c        11 Dec 2002 12:24:27 -0000      1.134
+++ main/alloc.c        11 Dec 2002 16:13:05 -0000
@@ -1687,12 +1687,17 @@
                                      void (*child_cleanup) (void *),
                                      int (*magic_cleanup) (void *))
 {
-    struct cleanup *c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
-    c->data = data;
-    c->plain_cleanup = plain_cleanup;
-    c->child_cleanup = child_cleanup;
-    c->next = p->cleanups;
-    p->cleanups = c;
+    struct cleanup *c;
+    if (p) {
+       c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
+       c->data = data;
+       c->plain_cleanup = plain_cleanup;
+       c->child_cleanup = child_cleanup;
+       c->next = p->cleanups;
+       p->cleanups = c;
+    }
+    /* attempt to do magic even if not passed a pool. Allows us
+     * to perform the magic, therefore, "whenever" we want/need */
     if(magic_cleanup) {
        if(!magic_cleanup(data)) 
           ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
@@ -1827,7 +1832,8 @@
     ap_kill_cleanup(p, (void *) (long) fd, fd_cleanup);
 }
 
-API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode)
+API_EXPORT(int) ap_popenf_ex(pool *a, const char *name, int flg, int mode,
+                             int domagic)
 {
     int fd;
     int save_errno;
@@ -1837,13 +1843,18 @@
     save_errno = errno;
     if (fd >= 0) {
        fd = ap_slack(fd, AP_SLACK_HIGH);
-       ap_note_cleanups_for_fd(a, fd);
+       ap_note_cleanups_for_fd_ex(a, fd, domagic);
     }
     ap_unblock_alarms();
     errno = save_errno;
     return fd;
 }
 
+API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode)
+{
+    return ap_popenf_ex(a, name, flg, mode, 0);
+}
+
 API_EXPORT(int) ap_pclosef(pool *a, int fd)
 {
     int res;
@@ -2059,7 +2070,7 @@
        errno = save_errno;
        return -1;
     }
-    ap_note_cleanups_for_socket(p, fd);
+    ap_note_cleanups_for_socket_ex(p, fd, 1); /* close socket on exec */
     ap_unblock_alarms();
     return fd;
 }
Index: main/http_main.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v
retrieving revision 1.596
diff -u -r1.596 http_main.c
--- main/http_main.c    25 Oct 2002 21:12:23 -0000      1.596
+++ main/http_main.c    11 Dec 2002 16:13:06 -0000
@@ -876,7 +876,7 @@
     unlock_it.l_pid = 0;               /* pid not actually interesting */
 
     expand_lock_fname(p);
-    lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
+    lock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644, 1);
     if (lock_fd == -1) {
        perror("open");
        fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname);
@@ -943,7 +943,7 @@
 static void accept_mutex_child_init_flock(pool *p)
 {
 
-    flock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600);
+    flock_fd = ap_popenf_ex(p, ap_lock_fname, O_WRONLY, 0600, 1);
     if (flock_fd == -1) {
        ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
                    "Child cannot open lock file: %s", ap_lock_fname);
@@ -959,7 +959,7 @@
 {
     expand_lock_fname(p);
     unlink(ap_lock_fname);
-    flock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600);
+    flock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600, 1);
     if (flock_fd == -1) {
        ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
                    "Parent cannot open lock file: %s", ap_lock_fname);
@@ -2457,7 +2457,7 @@
 #ifdef TPF
     ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
 #endif /* TPF */
-    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 
0666);
+    scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 
+0666, 1);
     if (scoreboard_fd == -1) {
        perror(ap_scoreboard_fname);
        fprintf(stderr, "Cannot open scoreboard file:\n");
@@ -2483,7 +2483,7 @@
     ap_scoreboard_image = &_scoreboard_image;
     ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
 
-    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 
0644);
+    scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 
+0644, 1);
     if (scoreboard_fd == -1) {
        perror(ap_scoreboard_fname);
        fprintf(stderr, "Cannot open scoreboard file:\n");
@@ -3655,7 +3655,7 @@
     s = ap_slack(s, AP_SLACK_HIGH);
 #endif
 
-    ap_note_cleanups_for_socket(p, s); /* arrange to close on exec or restart */
+    ap_note_cleanups_for_socket_ex(p, s, 1);   /* arrange to close on exec or restart 
+*/
 #ifdef TPF
     os_note_additional_cleanups(p, s);
 #endif /* TPF */
@@ -3796,7 +3796,7 @@
 #ifdef WORKAROUND_SOLARIS_BUG
     s = ap_slack(s, AP_SLACK_HIGH);
 
-    ap_note_cleanups_for_socket(p, s); /* arrange to close on exec or restart */
+    ap_note_cleanups_for_socket_ex(p, s, 1);   /* arrange to close on exec or restart 
+*/
 #endif
     ap_unblock_alarms();
 
@@ -3903,7 +3903,7 @@
            fd = make_sock(p, &lr->local_addr);
        }
        else {
-           ap_note_cleanups_for_socket(p, fd);
+           ap_note_cleanups_for_socket_ex(p, fd, 1);
        }
        /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */
        FD_SET(fd, &listenfds);
@@ -4517,7 +4517,7 @@
         */
        signal(SIGUSR1, SIG_IGN);
 
-       ap_note_cleanups_for_socket(ptrans, csd);
+       ap_note_cleanups_for_socket_ex(ptrans, csd, 1);
 
        /* protect various fd_sets */
 #ifdef CHECK_FD_SETSIZE
@@ -4565,7 +4565,7 @@
                        "dup: couldn't duplicate csd");
            dupped_csd = csd;   /* Oh well... */
        }
-       ap_note_cleanups_for_socket(ptrans, dupped_csd);
+       ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1);
 
        /* protect various fd_sets */
 #ifdef CHECK_FD_SETSIZE
@@ -5092,7 +5092,7 @@
 #ifdef SCOREBOARD_FILE
        else {
            ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
-           ap_note_cleanups_for_fd(pconf, scoreboard_fd);
+           ap_note_cleanups_for_fd_ex(pconf, scoreboard_fd, 1); /* close on exec */
        }
 #endif
 
@@ -5892,7 +5892,7 @@
 
        requests_this_child++;
 
-       ap_note_cleanups_for_socket(ptrans, csd);
+       ap_note_cleanups_for_socket_ex(ptrans, csd, 1);
 
        /*
         * We now have a connection, so set it up with the appropriate
@@ -5924,7 +5924,7 @@
                        "dup: couldn't duplicate csd");
            dupped_csd = csd;   /* Oh well... */
        }
-       ap_note_cleanups_for_socket(ptrans, dupped_csd);
+       ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1);
 #endif
        ap_bpushfd(conn_io, csd, dupped_csd);
 
@@ -6140,7 +6140,7 @@
             if (fd > listenmaxfd)
                 listenmaxfd = fd;
         }
-        ap_note_cleanups_for_socket(p, fd);
+        ap_note_cleanups_for_socket_ex(p, fd, 1);
         lr->fd = fd;
         if (lr->next == NULL) {
             /* turn the list into a ring */
Index: modules/standard/mod_log_agent.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_log_agent.c,v
retrieving revision 1.36
diff -u -r1.36 mod_log_agent.c
--- modules/standard/mod_log_agent.c    13 Mar 2002 21:05:33 -0000      1.36
+++ modules/standard/mod_log_agent.c    11 Dec 2002 16:13:06 -0000
@@ -125,7 +125,8 @@
         cls->agent_fd = ap_piped_log_write_fd(pl);
     }
     else if (*cls->fname != '\0') {
-        if ((cls->agent_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) {
+        if ((cls->agent_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+             < 0) {
             ap_log_error(APLOG_MARK, APLOG_ERR, s,
                          "could not open agent log file %s.", fname);
             exit(1);
Index: modules/standard/mod_log_config.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_log_config.c,v
retrieving revision 1.88
diff -u -r1.88 mod_log_config.c
--- modules/standard/mod_log_config.c   21 May 2002 13:03:56 -0000      1.88
+++ modules/standard/mod_log_config.c   11 Dec 2002 16:13:06 -0000
@@ -1069,7 +1069,8 @@
     }
     else {
         char *fname = ap_server_root_relative(p, cls->fname);
-        if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) {
+        if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+             < 0) {
             ap_log_error(APLOG_MARK, APLOG_ERR, s,
                          "could not open transfer log file %s.", fname);
             exit(1);
Index: modules/standard/mod_log_referer.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_log_referer.c,v
retrieving revision 1.39
diff -u -r1.39 mod_log_referer.c
--- modules/standard/mod_log_referer.c  13 Mar 2002 21:05:33 -0000      1.39
+++ modules/standard/mod_log_referer.c  11 Dec 2002 16:13:06 -0000
@@ -142,7 +142,8 @@
         cls->referer_fd = ap_piped_log_write_fd(pl);
     }
     else if (*cls->fname != '\0') {
-        if ((cls->referer_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) {
+        if ((cls->referer_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+             < 0) {
            ap_log_error(APLOG_MARK, APLOG_ERR, s,
                         "could not open referer log file %s.", fname);        
            exit(1);
Index: modules/standard/mod_mime_magic.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_mime_magic.c,v
retrieving revision 1.48
diff -u -r1.48 mod_mime_magic.c
--- modules/standard/mod_mime_magic.c   18 Jun 2002 01:00:00 -0000      1.48
+++ modules/standard/mod_mime_magic.c   11 Dec 2002 16:13:06 -0000
@@ -880,6 +880,7 @@
      * try looking at the first HOWMANY bytes
      */
     if ((nbytes = read(fd, (char *) buf, sizeof(buf) - 1)) == -1) {
+        (void) ap_pclosef(r->pool, fd);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
                    MODNAME ": read failed: %s", r->filename);
        return HTTP_INTERNAL_SERVER_ERROR;
Index: modules/standard/mod_rewrite.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.178
diff -u -r1.178 mod_rewrite.c
--- modules/standard/mod_rewrite.c      8 Jul 2002 17:18:32 -0000       1.178
+++ modules/standard/mod_rewrite.c      11 Dec 2002 16:13:07 -0000
@@ -3105,8 +3105,8 @@
         conf->rewritelogfp = ap_piped_log_write_fd(pl);
     }
     else if (*conf->rewritelogfile != '\0') {
-        if ((conf->rewritelogfp = ap_popenf(p, fname, rewritelog_flags,
-                                            rewritelog_mode)) < 0) {
+        if ((conf->rewritelogfp = ap_popenf_ex(p, fname, rewritelog_flags,
+                                            rewritelog_mode, 1)) < 0) {
             ap_log_error(APLOG_MARK, APLOG_ERR, s, 
 
                          "mod_rewrite: could not open RewriteLog "
@@ -3253,8 +3253,8 @@
 
     /* create the lockfile */
     unlink(lockname);
-    if ((lockfd = ap_popenf(p, lockname, O_WRONLY|O_CREAT,
-                                         REWRITELOCK_MODE)) < 0) {
+    if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY|O_CREAT,
+                                         REWRITELOCK_MODE, 1)) < 0) {
         ap_log_error(APLOG_MARK, APLOG_ERR, s,
                      "mod_rewrite: Parent could not create RewriteLock "
                      "file %s", lockname);
@@ -3281,8 +3281,8 @@
     }
 
     /* open the lockfile (once per child) to get a unique fd */
-    if ((lockfd = ap_popenf(p, lockname, O_WRONLY,
-                                         REWRITELOCK_MODE)) < 0) {
+    if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY,
+                                         REWRITELOCK_MODE, 1)) < 0) {
         ap_log_error(APLOG_MARK, APLOG_ERR, s,
                      "mod_rewrite: Child could not open RewriteLock "
                      "file %s", lockname);
Index: os/netware/mod_log_nw.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/os/netware/mod_log_nw.c,v
retrieving revision 1.3
diff -u -r1.3 mod_log_nw.c
--- os/netware/mod_log_nw.c     2 Apr 2002 16:51:01 -0000       1.3
+++ os/netware/mod_log_nw.c     11 Dec 2002 16:13:08 -0000
@@ -1161,7 +1161,7 @@
                 fname = ap_server_root_relative(p, cls->fname);
         }
             
-        if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) {
+        if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) < 0) {
             ap_log_error(APLOG_MARK, APLOG_ERR, s,
                          "could not open transfer log file %s.", fname);
             exit(1);

Reply via email to