Blob Blame History Raw
--- httpd-2.2.3/include/mpm_common.h.cve3304
+++ httpd-2.2.3/include/mpm_common.h
@@ -145,6 +145,17 @@
 #endif
 
 /**
+ * Safely signal an MPM child process, if the process is in the
+ * current process group.  Otherwise fail.
+ * @param pid the process id of a child process to signal
+ * @param sig the signal number to send
+ * @return APR_SUCCESS if signal is sent, otherwise an error as per kill(3)
+ */
+#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig);
+#endif
+
+/**
  * Determine if any child process has died.  If no child process died, then
  * this process sleeps for the amount of time specified by the MPM defined
  * macro SCOREBOARD_MAINTENANCE_INTERVAL.
--- httpd-2.2.3/server/mpm_common.c.cve3304
+++ httpd-2.2.3/server/mpm_common.c
@@ -126,6 +126,10 @@
     apr_proc_t proc;
     apr_status_t waitret;
 
+    if (!MPM_VALID_PID(pid)) {
+        return 1;
+    }
+
     proc.pid = pid;
     waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
     if (waitret != APR_CHILD_NOTDONE) {
@@ -305,6 +309,16 @@
         cur_extra = next;
     }
 }
+
+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
+{
+    if (MPM_VALID_PID(pid)) {
+        return kill(pid, sig) ? errno : APR_SUCCESS;
+    }
+    else {
+        return APR_EINVAL;
+    }
+}
 #endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */
 
 #ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT
--- httpd-2.2.3/server/mpm/prefork/prefork.c.cve3304
+++ httpd-2.2.3/server/mpm/prefork/prefork.c
@@ -1127,7 +1127,7 @@
         for (index = 0; index < ap_daemons_limit; ++index) {
             if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
                 /* Ask each child to close its listeners. */
-                kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
+                ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
                 active_children++;
             }
         }
@@ -1166,7 +1166,7 @@
             active_children = 0;
             for (index = 0; index < ap_daemons_limit; ++index) {
                 if (MPM_CHILD_PID(index) != 0) {
-                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                    if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == 0) {
                             active_children = 1;
                             /* Having just one child is enough to stay around */
                             break;
@@ -1222,7 +1222,7 @@
                  * piped loggers, etc. They almost certainly won't handle
                  * it gracefully.
                  */
-                kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
+                ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
             }
         }
     }
--- httpd-2.2.3/server/mpm/prefork/mpm.h.cve3304
+++ httpd-2.2.3/server/mpm/prefork/mpm.h
@@ -53,6 +53,7 @@
 #define AP_MPM_USES_POD 1
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
 #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
 #define MPM_ACCEPT_FUNC unixd_accept
 
 extern int ap_threads_per_child;
--- httpd-2.2.3/server/mpm/worker/worker.c.cve3304
+++ httpd-2.2.3/server/mpm/worker/worker.c
@@ -1814,7 +1814,7 @@
             active_children = 0;
             for (index = 0; index < ap_daemons_limit; ++index) {
                 if (MPM_CHILD_PID(index) != 0) {
-                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                    if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == 0) {
                             active_children = 1;
                             /* Having just one child is enough to stay around */
                             break;
--- httpd-2.2.3/server/mpm/worker/mpm.h.cve3304
+++ httpd-2.2.3/server/mpm/worker/mpm.h
@@ -52,6 +52,7 @@
 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
 #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
 #define MPM_ACCEPT_FUNC unixd_accept
+#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
 
 extern int ap_threads_per_child;
 extern int ap_max_daemons_limit;