unixd.c revision ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dc
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* Copyright 2000-2004 Apache Software Foundation
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Licensed under the Apache License, Version 2.0 (the "License");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * you may not use this file except in compliance with the License.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * You may obtain a copy of the License at
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * http://www.apache.org/licenses/LICENSE-2.0
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Unless required by applicable law or agreed to in writing, software
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * distributed under the License is distributed on an "AS IS" BASIS,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * See the License for the specific language governing permissions and
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * limitations under the License.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "ap_config.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#define CORE_PRIVATE
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "httpd.h"
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari#include "http_config.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "http_main.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "http_log.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "unixd.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "mpm_common.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "os.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "ap_mpm.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "apr_thread_proc.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "apr_strings.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "apr_portable.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_PWD_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <pwd.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_SYS_RESOURCE_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <sys/resource.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* XXX */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <sys/stat.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_UNISTD_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <unistd.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_GRP_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <grp.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_STRINGS_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <strings.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_SYS_SEM_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <sys/sem.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef HAVE_SYS_PRCTL_H
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include <sys/prctl.h>
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegariunixd_config_rec unixd_config;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* Set group privileges.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Note that we use the username as set in the config files, rather than
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * the lookup of to uid --- the same uid may have multiple passwd entries,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * with different sets of groups for each.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int set_group_privs(void)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!geteuid()) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char *name;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* Get username if passed as a uid */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (unixd_config.user_name[0] == '#') {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari struct passwd *ent;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari uid_t uid = atoi(&unixd_config.user_name[1]);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if ((ent = getpwuid(uid)) == NULL) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "getpwuid: couldn't determine user name from uid %u, "
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "you probably need to modify the User directive",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (unsigned)uid);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return -1;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari name = ent->pw_name;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari else
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari name = unixd_config.user_name;
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if !defined(OS2) && !defined(TPF)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* OS/2 and TPF don't support groups. */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Set the GID before initgroups(), since on some platforms
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * setgid() is known to zap the group list.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (setgid(unixd_config.group_id) == -1) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "setgid: unable to set group id to Group %u",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (unsigned)unixd_config.group_id);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return -1;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* Reset `groups' attributes. */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (initgroups(name, unixd_config.group_id) == -1) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "initgroups: unable to set groups for User %s "
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "and Group %u", name, (unsigned)unixd_config.group_id);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return -1;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#endif /* !defined(OS2) && !defined(TPF) */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return 0;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(int) unixd_setup_child(void)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (set_group_privs()) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return -1;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef MPE
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* Only try to switch if we're running as MANAGER.SYS */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (geteuid() == 1 && unixd_config.user_id > 1) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari GETPRIVMODE();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (setuid(unixd_config.user_id) == -1) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari GETUSERMODE();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "setuid: unable to change to uid: %ld",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (long) unixd_config.user_id);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari exit(1);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari GETUSERMODE();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari#else
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* Only try to switch if we're running as root */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!geteuid() && (
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari#ifdef _OSD_POSIX
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari os_init_job_environment(NULL, unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 ||
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari setuid(unixd_config.user_id) == -1)) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "setuid: unable to change to uid: %ld",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (long) unixd_config.user_id);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return -1;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* this applies to Linux 2.4+ */
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari#ifdef AP_MPM_WANT_SET_COREDUMPDIR
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (ap_coredumpdir_configured) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (prctl(PR_SET_DUMPABLE, 1)) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari "set dumpable failed - this child will not coredump"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari " after software errors");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari }
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari#endif
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return 0;
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari}
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(const char *) unixd_set_user(cmd_parms *cmd, void *dummy,
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari const char *arg)
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (err != NULL) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return err;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari unixd_config.user_name = arg;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari unixd_config.user_id = ap_uname2id(arg);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if !defined (BIG_SECURITY_HOLE) && !defined (OS2)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (unixd_config.user_id == 0) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return "Error:\tApache has not been designed to serve pages while\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\trunning as root. There are known race conditions that\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\twill allow any local user to read any file on the system.\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\tIf you still desire to serve pages as root then\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\tadd -DBIG_SECURITY_HOLE to the CFLAGS env variable\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\tand then rebuild the server.\n"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "\tIt is strongly suggested that you instead modify the User\n"
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari "\tdirective in your httpd.conf file to list a non-root\n"
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari "\tuser.\n";
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return NULL;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari}
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel CalegariAP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari const char *arg)
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari{
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (err != NULL) {
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari return err;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari unixd_config.group_id = ap_gname2id(arg);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return NULL;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari}
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel CalegariAP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari{
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari apr_finfo_t wrapper;
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari unixd_config.user_name = DEFAULT_USER;
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari unixd_config.user_id = ap_uname2id(DEFAULT_USER);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /* Check for suexec */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari unixd_config.suexec_enabled = 0;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ((apr_stat(&wrapper, SUEXEC_BIN,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari APR_FINFO_NORM, ptemp)) != APR_SUCCESS) {
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari return;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /* XXX - apr_stat is incapable of checking suid bits (grumble) */
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari /* if ((wrapper.filetype & S_ISUID) && wrapper.user == 0) { */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari unixd_config.suexec_enabled = 1;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari /* } */
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari}
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari
b767e7055b5ef62c990a111ac0524500592f8781Daniel CalegariAP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari const char *arg, const char * arg2, int type)
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari{
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari#if (defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)) && APR_HAVE_STRUCT_RLIMIT && APR_HAVE_GETRLIMIT
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari char *str;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari struct rlimit *limit;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari /* If your platform doesn't define rlim_t then typedef it in ap_config.h */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari rlim_t cur = 0;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari rlim_t max = 0;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari *plimit = (struct rlimit *)apr_pcalloc(cmd->pool, sizeof(**plimit));
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari limit = *plimit;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ((getrlimit(type, limit)) != 0) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari *plimit = NULL;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ERR, errno, cmd->server,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari "%s: getrlimit failed", cmd->cmd->name);
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari return;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ((str = ap_getword_conf(cmd->pool, &arg))) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (!strcasecmp(str, "max")) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari cur = limit->rlim_max;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari else {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari cur = atol(str);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari else {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari "Invalid parameters for %s", cmd->cmd->name);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari max = atol(str);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /* if we aren't running as root, cannot increase max */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (geteuid()) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari limit->rlim_cur = cur;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (max) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari "Must be uid 0 to raise maximum %s", cmd->cmd->name);
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari else {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (cur) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari limit->rlim_cur = cur;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (max) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari limit->rlim_max = max;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#else
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari "Platform does not support rlimit for %s", cmd->cmd->name);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#endif
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari}
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel CalegariAPR_HOOK_STRUCT(
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari APR_HOOK_LINK(get_suexec_identity)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel CalegariAP_IMPLEMENT_HOOK_RUN_FIRST(ap_unix_identity_t *, get_suexec_identity,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari (const request_rec *r), (r), NULL)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegaristatic apr_status_t ap_unix_create_privileged_process(
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari apr_proc_t *newproc, const char *progname,
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari const char * const *args,
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari const char * const *env,
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari apr_procattr_t *attr, ap_unix_identity_t *ugid,
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari apr_pool_t *p)
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari{
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari int i = 0;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari const char **newargs;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari char *newprogname;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari char *execuser, *execgroup;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari const char *argv0;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (!unixd_config.suexec_enabled) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari return apr_proc_create(newproc, progname, args, env, attr, p);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari argv0 = ap_strrchr_c(progname, '/');
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari /* Allow suexec's "/" check to succeed */
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (argv0 != NULL) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari argv0++;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari else {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari argv0 = progname;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (ugid->userdir) {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari execuser = apr_psprintf(p, "~%ld", (long) ugid->uid);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari else {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari execuser = apr_psprintf(p, "%ld", (long) ugid->uid);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari execgroup = apr_psprintf(p, "%ld", (long) ugid->gid);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (!execuser || !execgroup) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari return APR_ENOMEM;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari i = 0;
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (args) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari while (args[i]) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari i++;
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /* allocate space for 4 new args, the input args, and a null terminator */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari newargs = apr_palloc(p, sizeof(char *) * (i + 4));
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari newprogname = SUEXEC_BIN;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari newargs[0] = SUEXEC_BIN;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari newargs[1] = execuser;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari newargs[2] = execgroup;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari newargs[3] = apr_pstrdup(p, argv0);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari /*
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ** using a shell to execute suexec makes no sense thus
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ** we force everything to be APR_PROGRAM, and never
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari ** APR_SHELLCMD
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if(apr_procattr_cmdtype_set(attr, APR_PROGRAM) != APR_SUCCESS) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return APR_EGENERAL;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari i = 1;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari do {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari newargs[i + 3] = args[i];
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari } while (args[i++]);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return apr_proc_create(newproc, newprogname, newargs, env, attr, p);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(apr_status_t) ap_os_create_privileged_process(
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const request_rec *r,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_proc_t *newproc, const char *progname,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char * const *args,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char * const *env,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_procattr_t *attr, apr_pool_t *p)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_unix_identity_t *ugid = ap_run_get_suexec_identity(r);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (ugid == NULL) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return apr_proc_create(newproc, progname, args, env, attr, p);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return ap_unix_create_privileged_process(newproc, progname, args, env,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari attr, ugid, p);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* XXX move to APR and externalize (but implement differently :) ) */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic apr_lockmech_e proc_mutex_mech(apr_proc_mutex_t *pmutex)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char *mechname = apr_proc_mutex_name(pmutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!strcmp(mechname, "sysvsem")) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return APR_LOCK_SYSVSEM;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari else if (!strcmp(mechname, "flock")) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari return APR_LOCK_FLOCK;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return APR_LOCK_DEFAULT;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex)
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!geteuid()) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_lockmech_e mech = proc_mutex_mech(pmutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari switch(mech) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if APR_HAS_SYSVSEM_SERIALIZE
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari case APR_LOCK_SYSVSEM:
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_os_proc_mutex_t ospmutex;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if !APR_HAVE_UNION_SEMUN
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari union semun {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari long val;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari struct semid_ds *buf;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari unsigned short *array;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari };
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari union semun ick;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari struct semid_ds buf;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_os_proc_mutex_get(&ospmutex, pmutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari buf.sem_perm.uid = unixd_config.user_id;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari buf.sem_perm.gid = unixd_config.group_id;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari buf.sem_perm.mode = 0600;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ick.buf = &buf;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return errno;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari break;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if APR_HAS_FLOCK_SERIALIZE
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari case APR_LOCK_FLOCK:
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari const char *lockfile = apr_proc_mutex_lockfile(pmutex);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (lockfile) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (chown(lockfile, unixd_config.user_id,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari -1 /* no gid change */) < 0) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return errno;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari break;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari default:
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* do nothing */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari break;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari return APR_SUCCESS;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(apr_status_t) unixd_set_global_mutex_perms(apr_global_mutex_t *gmutex)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if !APR_PROC_MUTEX_IS_GLOBAL
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_os_global_mutex_t osgmutex;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_os_global_mutex_get(&osgmutex, gmutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return unixd_set_proc_mutex_perms(osgmutex.proc_mutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#else /* APR_PROC_MUTEX_IS_GLOBAL */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* In this case, apr_proc_mutex_t and apr_global_mutex_t are the same. */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return unixd_set_proc_mutex_perms(gmutex);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif /* APR_PROC_MUTEX_IS_GLOBAL */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel CalegariAP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_pool_t *ptrans)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_socket_t *csd;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari apr_status_t status;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari int sockdes;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *accepted = NULL;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari status = apr_socket_accept(&csd, lr->sd, ptrans);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (status == APR_SUCCESS) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *accepted = csd;
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari apr_os_sock_get(&sockdes, csd);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari#ifdef TPF
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari if (sockdes == 0) { /* 0 is invalid socket for TPF */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return APR_EINTR;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return status;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (APR_STATUS_IS_EINTR(status)) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return status;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* Our old behaviour here was to continue after accept()
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * errors. But this leads us into lots of troubles
* because most of the errors are quite fatal. For
* example, EMFILE can be caused by slow descriptor
* leaks (say in a 3rd party module, or libc). It's
* foolish for us to continue after an EMFILE. We also
* seem to tickle kernel bugs on some platforms which
* lead to never-ending loops here. So it seems best
* to just exit in most cases.
*/
switch (status) {
#if defined(HPUX11) && defined(ENOBUFS)
/* On HPUX 11.x, the 'ENOBUFS, No buffer space available'
* error occurs because the accept() cannot complete.
* You will not see ENOBUFS with 10.20 because the kernel
* hides any occurrence from being returned to user space.
* ENOBUFS with 11.x's TCP/IP stack is possible, and could
* occur intermittently. As a work-around, we are going to
* ignore ENOBUFS.
*/
case ENOBUFS:
#endif
#ifdef EPROTO
/* EPROTO on certain older kernels really means
* ECONNABORTED, so we need to ignore it for them.
* See discussion in new-httpd archives nh.9701
* search for EPROTO.
*
* Also see nh.9603, search for EPROTO:
* There is potentially a bug in Solaris 2.x x<6,
* and other boxes that implement tcp sockets in
* userland (i.e. on top of STREAMS). On these
* systems, EPROTO can actually result in a fatal
* loop. See PR#981 for example. It's hard to
* handle both uses of EPROTO.
*/
case EPROTO:
#endif
#ifdef ECONNABORTED
case ECONNABORTED:
#endif
/* Linux generates the rest of these, other tcp
* stacks (i.e. bsd) tend to hide them behind
* getsockopt() interfaces. They occur when
* the net goes sour or the client disconnects
* after the three-way handshake has been done
* in the kernel but before userland has picked
* up the socket.
*/
#ifdef ECONNRESET
case ECONNRESET:
#endif
#ifdef ETIMEDOUT
case ETIMEDOUT:
#endif
#ifdef EHOSTUNREACH
case EHOSTUNREACH:
#endif
#ifdef ENETUNREACH
case ENETUNREACH:
#endif
break;
#ifdef ENETDOWN
case ENETDOWN:
/*
* When the network layer has been shut down, there
* is not much use in simply exiting: the parent
* would simply re-create us (and we'd fail again).
* Use the CHILDFATAL code to tear the server down.
* @@@ Martin's idea for possible improvement:
* A different approach would be to define
* a new APEXIT_NETDOWN exit code, the reception
* of which would make the parent shutdown all
* children, then idle-loop until it detected that
* the network is up again, and restart the children.
* Ben Hyde noted that temporary ENETDOWN situations
* occur in mobile IP.
*/
ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
"apr_socket_accept: giving up.");
return APR_EGENERAL;
#endif /*ENETDOWN*/
#ifdef TPF
case EINACT:
ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
"offload device inactive");
return APR_EGENERAL;
break;
default:
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
"select/accept error (%d)", status);
return APR_EGENERAL;
#else
default:
ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf,
"apr_socket_accept: (client socket)");
return APR_EGENERAL;
#endif
}
return status;
}