You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jo...@apache.org on 2007/07/17 16:48:27 UTC
svn commit: r556936 - in /httpd/httpd/branches/2.2.x: CHANGES configure.in
include/ap_mmn.h include/mpm_common.h server/mpm/experimental/event/event.c
server/mpm/prefork/prefork.c server/mpm/worker/worker.c server/mpm_common.c
Author: jorton
Date: Tue Jul 17 07:48:25 2007
New Revision: 556936
URL: http://svn.apache.org/viewvc?view=rev&rev=556936
Log:
Merge r551843, r551889 from trunk:
Add alternative fixes for CVE-2007-3304:
* configure.in: Check for getpgid.
* include/mpm_common.h (ap_mpm_safe_kill): New prototype.
* server/mpm_common.c (reclaim_one_pid): Ensure pid validity before
calling apr_proc_wait().
(ap_mpm_safe_kill): New function.
* server/mpm/prefork/prefork.c, server/mpm/worker/worker.c,
server/mpm/experimental/event/event.c: Use ap_mpm_safe_kill() on pids
from the scoreboard, throughout.
* include/ap_mmn.h: Minor bump.
* server/mpm_common.c: getpgid() returns a pid_t
Submitted by: jorton, jim
Reviewed by: jorton, jim, rpluem
Modified:
httpd/httpd/branches/2.2.x/CHANGES
httpd/httpd/branches/2.2.x/configure.in
httpd/httpd/branches/2.2.x/include/ap_mmn.h
httpd/httpd/branches/2.2.x/include/mpm_common.h
httpd/httpd/branches/2.2.x/server/mpm/experimental/event/event.c
httpd/httpd/branches/2.2.x/server/mpm/prefork/prefork.c
httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c
httpd/httpd/branches/2.2.x/server/mpm_common.c
Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Tue Jul 17 07:48:25 2007
@@ -6,6 +6,11 @@
Cache-Control header without any value.
[Niklas Edmundsson <nikke acc.umu.se>]
+ *) SECURITY: CVE-2007-3304 (cve.mitre.org)
+ prefork, worker, event MPMs: Ensure that the parent process cannot
+ be forced to kill processes outside its process group.
+ [Joe Orton, Jim Jagielski]
+
*) mod_cache: Do not set Date or Expires when they are missing from
the original response or are invalid. [Justin Erenkrantz]
Modified: httpd/httpd/branches/2.2.x/configure.in
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/configure.in?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/configure.in (original)
+++ httpd/httpd/branches/2.2.x/configure.in Tue Jul 17 07:48:25 2007
@@ -392,6 +392,7 @@
bindprocessor \
prctl \
timegm \
+getpgid
)
dnl confirm that a void pointer is large enough to store a long integer
Modified: httpd/httpd/branches/2.2.x/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/ap_mmn.h?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/include/ap_mmn.h (original)
+++ httpd/httpd/branches/2.2.x/include/ap_mmn.h Tue Jul 17 07:48:25 2007
@@ -113,6 +113,8 @@
* 20051115.3 (2.2.3) Added server_scheme member to server_rec (minor)
* 20051115.4 (2.2.4) Added ap_get_server_banner() and
* ap_get_server_description() (minor)
+ * 20051115.5 (2.2.5) Added ap_mpm_safe_kill() (minor)
+ *
*/
#define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
@@ -120,7 +122,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20051115
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 4 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Modified: httpd/httpd/branches/2.2.x/include/mpm_common.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/mpm_common.h?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/include/mpm_common.h (original)
+++ httpd/httpd/branches/2.2.x/include/mpm_common.h Tue Jul 17 07:48:25 2007
@@ -145,6 +145,19 @@
#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);
+ * APR_EINVAL is returned if passed either an invalid (< 1) pid, or if
+ * the pid is not in the current process group
+ */
+#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.
Modified: httpd/httpd/branches/2.2.x/server/mpm/experimental/event/event.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/mpm/experimental/event/event.c?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/server/mpm/experimental/event/event.c (original)
+++ httpd/httpd/branches/2.2.x/server/mpm/experimental/event/event.c Tue Jul 17 07:48:25 2007
@@ -1998,12 +1998,10 @@
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) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
Modified: httpd/httpd/branches/2.2.x/server/mpm/prefork/prefork.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/mpm/prefork/prefork.c?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/server/mpm/prefork/prefork.c (original)
+++ httpd/httpd/branches/2.2.x/server/mpm/prefork/prefork.c Tue Jul 17 07:48:25 2007
@@ -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++;
}
}
@@ -1165,12 +1165,10 @@
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) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
@@ -1222,7 +1220,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);
}
}
}
Modified: httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c (original)
+++ httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c Tue Jul 17 07:48:25 2007
@@ -1813,12 +1813,10 @@
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) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
Modified: httpd/httpd/branches/2.2.x/server/mpm_common.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/mpm_common.c?view=diff&rev=556936&r1=556935&r2=556936
==============================================================================
--- httpd/httpd/branches/2.2.x/server/mpm_common.c (original)
+++ httpd/httpd/branches/2.2.x/server/mpm_common.c Tue Jul 17 07:48:25 2007
@@ -126,6 +126,11 @@
apr_proc_t proc;
apr_status_t waitret;
+ /* Ensure pid sanity. */
+ if (pid < 1) {
+ return 1;
+ }
+
proc.pid = pid;
waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
if (waitret != APR_CHILD_NOTDONE) {
@@ -304,6 +309,66 @@
}
cur_extra = next;
}
+}
+
+/* Before sending the signal to the pid this function verifies that
+ * the pid is a member of the current process group; either using
+ * apr_proc_wait(), where waitpid() guarantees to fail for non-child
+ * processes; or by using getpgid() directly, if available. */
+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
+{
+#ifndef HAVE_GETPGID
+ apr_proc_t proc;
+ apr_status_t rv;
+ apr_exit_why_e why;
+ int status;
+
+ /* Ensure pid sanity */
+ if (pid < 1) {
+ return APR_EINVAL;
+ }
+
+ proc.pid = pid;
+ rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT);
+ if (rv == APR_CHILD_DONE) {
+#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS
+ /* The child already died - log the termination status if
+ * necessary: */
+ ap_process_child_status(&proc, why, status);
+#endif
+ return APR_EINVAL;
+ }
+ else if (rv != APR_CHILD_NOTDONE) {
+ /* The child is already dead and reaped, or was a bogus pid -
+ * log this either way. */
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf,
+ "cannot send signal %d to pid %ld (non-child or "
+ "already dead)", sig, (long)pid);
+ return APR_EINVAL;
+ }
+#else
+ pid_t pg;
+
+ /* Ensure pid sanity. */
+ if (pid < 1) {
+ return APR_EINVAL;
+ }
+
+ pg = getpgid(pid);
+ if (pg == -1) {
+ /* Process already dead... */
+ return errno;
+ }
+
+ if (pg != getpgrp()) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf,
+ "refusing to send signal %d to pid %ld outside "
+ "process group", sig, (long)pid);
+ return APR_EINVAL;
+ }
+#endif
+
+ return kill(pid, sig) ? errno : APR_SUCCESS;
}
#endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */