--- 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;