diff --git a/CHANGES b/CHANGES index d3c4f8d828..e2509e32fd 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) Unix: Handle permissions settings for flock-based mutexes in + unixd_set_global|proc_mutex_perms(). Allow the functions to be + called for any type of mutex. PR 20312 [Jeff Trawick] + *) mod_rewrite: Perform child initialization on the rewrite log lock. This fixes a log corruption issue when flock-based serialization is used (e.g., FreeBSD). [Jeff Trawick] diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 4ef13a2710..7880255a0e 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -118,6 +118,7 @@ #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) #include "unixd.h" +#define MOD_REWRITE_SET_MUTEX_PERMS /* XXX Apache should define something */ #endif /* @@ -1017,7 +1018,7 @@ static int post_config(apr_pool_t *p, return HTTP_INTERNAL_SERVER_ERROR; } -#if APR_USE_SYSVSEM_SERIALIZE +#ifdef MOD_REWRITE_SET_MUTEX_PERMS rv = unixd_set_global_mutex_perms(rewrite_log_lock); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, @@ -3585,7 +3586,7 @@ static apr_status_t rewritelock_create(server_rec *s, apr_pool_t *p) return rc; } -#if APR_USE_SYSVSEM_SERIALIZE +#ifdef MOD_REWRITE_SET_MUTEX_PERMS rc = unixd_set_global_mutex_perms(rewrite_mapr_lock_acquire); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s, diff --git a/modules/ssl/mod_ssl.h b/modules/ssl/mod_ssl.h index 971a012dc1..dc3b3a8450 100644 --- a/modules/ssl/mod_ssl.h +++ b/modules/ssl/mod_ssl.h @@ -394,7 +394,6 @@ typedef struct { ssl_mutexmode_t nMutexMode; apr_lockmech_e nMutexMech; const char *szMutexFile; - BOOL ChownMutexFile; apr_global_mutex_t *pMutex; apr_array_header_t *aRandSeed; apr_hash_t *tVHostKeys; diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index b330729333..97697bee47 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -101,7 +101,6 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s) mc->nMutexMode = SSL_MUTEXMODE_UNSET; mc->nMutexMech = APR_LOCK_DEFAULT; mc->szMutexFile = NULL; - mc->ChownMutexFile = FALSE; mc->pMutex = NULL; mc->aRandSeed = apr_array_make(pool, 4, sizeof(ssl_randseed_t)); @@ -401,7 +400,6 @@ const char *ssl_cmd_SSLMutex(cmd_parms *cmd, */ mc->nMutexMode = SSL_MUTEXMODE_USED; mc->szMutexFile = NULL; - mc->ChownMutexFile = FALSE; /* NOTE: previously, 'yes' implied 'sem' */ if (!strcasecmp(meth, "default") || !strcasecmp(meth, "yes")) { @@ -415,7 +413,6 @@ const char *ssl_cmd_SSLMutex(cmd_parms *cmd, #if APR_HAS_FLOCK_SERIALIZE else if ((!strcasecmp(meth, "flock") || !strcasecmp(meth, "file")) && file) { mc->nMutexMech = APR_LOCK_FLOCK; - mc->ChownMutexFile = TRUE; } #endif #if APR_HAS_POSIXSEM_SERIALIZE diff --git a/modules/ssl/ssl_engine_mutex.c b/modules/ssl/ssl_engine_mutex.c index ad029b02d7..dbb95bb262 100644 --- a/modules/ssl/ssl_engine_mutex.c +++ b/modules/ssl/ssl_engine_mutex.c @@ -63,6 +63,7 @@ #include "mod_ssl.h" #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) #include "unixd.h" +#define MOD_SSL_SET_MUTEX_PERMS /* XXX Apache should define something */ #endif int ssl_mutex_init(server_rec *s, apr_pool_t *p) @@ -88,25 +89,14 @@ int ssl_mutex_init(server_rec *s, apr_pool_t *p) "Cannot create SSLMutex"); return FALSE; } -#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) - if (mc->szMutexFile && mc->ChownMutexFile == TRUE) - chown(mc->szMutexFile, unixd_config.user_id, -1); -#endif -#if APR_HAS_SYSVSEM_SERIALIZE -#if APR_USE_SYSVSEM_SERIALIZE - if (mc->nMutexMech == APR_LOCK_DEFAULT || - mc->nMutexMech == APR_LOCK_SYSVSEM) { -#else - if (mc->nMutexMech == APR_LOCK_SYSVSEM) { -#endif - rv = unixd_set_global_mutex_perms(mc->pMutex); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "Could not set permissions on ssl_mutex; check User " - "and Group directives"); - return FALSE; - } +#ifdef MOD_SSL_SET_MUTEX_PERMS + rv = unixd_set_global_mutex_perms(mc->pMutex); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "Could not set permissions on ssl_mutex; check User " + "and Group directives"); + return FALSE; } #endif return TRUE; diff --git a/os/unix/unixd.c b/os/unix/unixd.c index 11feda653c..d5b6c90b8e 100644 --- a/os/unix/unixd.c +++ b/os/unix/unixd.c @@ -417,35 +417,70 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process( attr, ugid, p); } +/* XXX move to APR and externalize (but implement differently :) ) */ +static apr_lockmech_e proc_mutex_mech(apr_proc_mutex_t *pmutex) +{ + const char *mechname = apr_proc_mutex_name(pmutex); + + if (!strcmp(mechname, "sysvsem")) { + return APR_LOCK_SYSVSEM; + } + else if (!strcmp(mechname, "flock")) { + return APR_LOCK_FLOCK; + } + return APR_LOCK_DEFAULT; +} + AP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex) { -/* 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_proc_mutex_t ospmutex; -#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_proc_mutex_get(&ospmutex, pmutex); - 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(ospmutex.crossproc, 0, IPC_SET, ick) < 0) { - return errno; + apr_lockmech_e mech = proc_mutex_mech(pmutex); + + switch(mech) { +#if APR_HAS_SYSVSEM_SERIALIZE + case APR_LOCK_SYSVSEM: + { + apr_os_proc_mutex_t ospmutex; +#if !APR_HAVE_UNION_SEMUN + union semun { + long val; + struct semid_ds *buf; + ushort *array; + }; +#endif + union semun ick; + struct semid_ds buf; + + apr_os_proc_mutex_get(&ospmutex, pmutex); + 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(ospmutex.crossproc, 0, IPC_SET, ick) < 0) { + return errno; + } + } + break; +#endif +#if APR_HAS_FLOCK_SERIALIZE + case APR_LOCK_FLOCK: + { + const char *lockfile = apr_proc_mutex_lockfile(pmutex); + + if (lockfile) { + if (chown(lockfile, unixd_config.user_id, + -1 /* no gid change */) < 0) { + return errno; + } + } + } + break; +#endif + default: + /* do nothing */ + break; } } -#endif return APR_SUCCESS; } diff --git a/os/unix/unixd.h b/os/unix/unixd.h index ba18098542..1f3f4691e9 100644 --- a/os/unix/unixd.h +++ b/os/unix/unixd.h @@ -120,6 +120,16 @@ AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy, AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg, const char * arg2, int type); #endif + +/** + * One of the functions to set mutex permissions should be called in + * the parent process on platforms that switch identity when the + * server is started as root. + * If the child init logic is performed before switching identity + * (e.g., MPM setup for an accept mutex), it should only be called + * for SysV semaphores. Otherwise, it is safe to call it for all + * mutex types. + */ AP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex); AP_DECLARE(apr_status_t) unixd_set_global_mutex_perms(apr_global_mutex_t *gmutex); AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr, apr_pool_t *ptrans);