processes to use the accept mutex when starting as root and
using SysV sems for the accept mutex. Previously, this
combination would lead to fatal errors in the child server
processes. perchild can't use SysV sems because of security
issues.
translation: steal apache 1.3 code to call semop(IPC_SET) on
the semaphore to set permissions and uid/gid
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90213
13f79535-47bb-0310-9956-
ffa450edef68
Changes with Apache 2.0.24-dev
+ *) The Unix MPMs other than perchild now allow child server
+ processes to use the accept mutex when starting as root and
+ using SysV sems for the accept mutex. Previously, this
+ combination would lead to fatal errors in the child server
+ processes. perchild can't use SysV sems because of security
+ issues. [Jeff Trawick, Greg Ames]
+
*) Added Win32 revision stamp resources to all http binaries
(including modules/ and support/ tools.) PR7322 [William Rowe]
pwd.h \
grp.h \
strings.h \
-sys/processor.h
+sys/processor.h \
+sys/sem.h
)
AC_HEADER_SYS_WAIT
#include "ap_mpm.h"
#include "apr_thread_proc.h"
#include "apr_strings.h"
+#include "apr_portable.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
+#ifdef HAVE_SYS_SEM_H
+#include <sys/sem.h>
+#endif
unixd_config_rec unixd_config;
attr, ugid, p);
}
+AP_DECLARE(apr_status_t) unixd_set_lock_perms(apr_lock_t *lock)
+{
+/* MPM shouldn't call us unless we're actually using a SysV sem;
+ * this is just to avoid compile issues on systems without that
+ * feature
+ */
+#if APR_HAS_SYSVSEM_SERIALIZE
+ apr_os_lock_t oslock;
+#if !APR_HAVE_UNION_SEMUN
+ union semun {
+ long val;
+ struct semid_ds *buf;
+ ushort *array;
+};
+#endif
+ union semun ick;
+ struct semid_ds buf;
+
+ if (!geteuid()) {
+ apr_os_lock_get(&oslock, lock);
+ buf.sem_perm.uid = unixd_config.user_id;
+ buf.sem_perm.gid = unixd_config.group_id;
+ buf.sem_perm.mode = 0600;
+ ick.buf = &buf;
+ if (semctl(oslock.crossproc, 0, IPC_SET, ick) < 0) {
+ return errno;
+ }
+ }
+#endif
+ return APR_SUCCESS;
+}
+
#endif
#include "apr_hooks.h"
#include "apr_thread_proc.h"
+#include "apr_lock.h"
#include <pwd.h>
#include <grp.h>
AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit,
const char *arg, const char * arg2, int type);
#endif
-
+AP_DECLARE(apr_status_t) unixd_set_lock_perms(apr_lock_t *lock);
#ifdef HAVE_KILLPG
#define unixd_killpg(x, y) (killpg ((x), (y)))
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't create accept mutex");
exit(APEXIT_INIT);
}
+
+#if APR_USE_SYSVSEM_SERIALIZE
+ if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
+ ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#else
+ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#endif
+ rv = unixd_set_lock_perms(accept_lock);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL,
+ "Couldn't set permissions on cross-process lock");
+ exit(APEXIT_INIT);
+ }
+ }
}
static void accept_mutex_on(void)
return 1;
}
+#if APR_USE_SYSVSEM_SERIALIZE
+ if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
+ ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#else
+ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#endif
+ rv = unixd_set_lock_perms(accept_mutex);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
+ "Couldn't set permissions on cross-process lock");
+ return 1;
+ }
+ }
+
if (!is_graceful) {
ap_run_pre_mpm(pconf, SB_SHARED);
}
return 1;
}
+#if APR_USE_SYSVSEM_SERIALIZE
+ if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
+ ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#else
+ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+#endif
+ rv = unixd_set_lock_perms(accept_mutex);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
+ "Couldn't set permissions on cross-process lock");
+ return 1;
+ }
+ }
+
if (!is_graceful) {
ap_run_pre_mpm(pconf, SB_SHARED);
}
ap_accept_lock_mech = APR_LOCK_FCNTL;
}
#endif
-#if APR_HAS_SYSVSEM_SERIALIZE
+ /* perchild can't use SysV sems because the permissions on the accept
+ * mutex can't be set to allow all processes to use the mutex and
+ * at the same time keep all users from being able to dink with the
+ * mutex
+ */
+#if APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM)
else if (!strcasecmp(arg, "sysvsem")) {
ap_accept_lock_mech = APR_LOCK_SYSVSEM;
}
#endif
else {
return apr_pstrcat(cmd->pool, arg, " is an invalid mutex mechanism; valid "
- "ones for this platform are: default"
+ "ones for this platform and MPM are: default"
#if APR_HAS_FLOCK_SERIALIZE
", flock"
#endif
#if APR_HAS_FCNTL_SERIALIZE
", fcntl"
#endif
-#if APR_HAS_SYSVSEM_SERIALIZE
+#if APR_HAS_SYSVSEM_SERIALIZE && !defined(PERCHILD_MPM)
", sysvsem"
#endif
#if APR_HAS_PROC_PTHREAD_SERIALIZE