]> granicus.if.org Git - apache/blobdiff - os/unix/unixd.c
* os/unix/unixd.c (unixd_accept): Eliminate now-redundant call to
[apache] / os / unix / unixd.c
index c21868e38851c12b505f2fee81831ce898d6f7a7..082b3cf6a7d58eadad5cf98174a717599933dbe0 100644 (file)
@@ -1,59 +1,16 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* Copyright 1999-2004 The Apache Software Foundation
  *
- * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
- * reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include "ap_config.h"
@@ -89,6 +46,9 @@
 #ifdef HAVE_SYS_SEM_H
 #include <sys/sem.h>
 #endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
 
 unixd_config_rec unixd_config;
 
@@ -173,7 +133,7 @@ AP_DECLARE(int) unixd_setup_child(void)
     /* Only try to switch if we're running as root */
     if (!geteuid() && (
 #ifdef _OSD_POSIX
-       os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 || 
+       os_init_job_environment(NULL, unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 ||
 #endif
        setuid(unixd_config.user_id) == -1)) {
        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
@@ -181,6 +141,18 @@ AP_DECLARE(int) unixd_setup_child(void)
                     (long) unixd_config.user_id);
        return -1;
     }
+#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) 
+    /* this applies to Linux 2.4+ */
+#ifdef AP_MPM_WANT_SET_COREDUMPDIR
+    if (ap_coredumpdir_configured) {
+        if (prctl(PR_SET_DUMPABLE, 1)) {
+            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
+                         "set dumpable failed - this child will not coredump"
+                         " after software errors");
+        }
+    }
+#endif
+#endif
 #endif
     return 0;
 }
@@ -326,11 +298,22 @@ static apr_status_t ap_unix_create_privileged_process(
     const char **newargs;
     char *newprogname;
     char *execuser, *execgroup;
+    const char *argv0;
 
     if (!unixd_config.suexec_enabled) {
         return apr_proc_create(newproc, progname, args, env, attr, p);
     }
 
+    argv0 = ap_strrchr_c(progname, '/');
+    /* Allow suexec's "/" check to succeed */
+    if (argv0 != NULL) {
+        argv0++;
+    }
+    else {
+        argv0 = progname;
+    }
+
+
     if (ugid->userdir) {
         execuser = apr_psprintf(p, "~%ld", (long) ugid->uid);
     }
@@ -355,7 +338,7 @@ static apr_status_t ap_unix_create_privileged_process(
     newargs[0] = SUEXEC_BIN;
     newargs[1] = execuser;
     newargs[2] = execgroup;
-    newargs[3] = apr_pstrdup(p, progname);
+    newargs[3] = apr_pstrdup(p, argv0);
 
     /*
     ** using a shell to execute suexec makes no sense thus
@@ -391,35 +374,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 (!geteuid()) {
+        apr_lockmech_e mech = proc_mutex_mech(pmutex);
+
+        switch(mech) {
 #if APR_HAS_SYSVSEM_SERIALIZE
-    apr_os_proc_mutex_t ospmutex;
+        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;
-    };
+            union semun {
+                long val;
+                struct semid_ds *buf;
+                unsigned short *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;
+            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;
+        }
+    }
     return APR_SUCCESS;
 }
 
@@ -440,28 +458,12 @@ AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr,
 {
     apr_socket_t *csd;
     apr_status_t status;
-    int sockdes;
 
     *accepted = NULL;
-    status = apr_accept(&csd, lr->sd, ptrans);
+    status = apr_socket_accept(&csd, lr->sd, ptrans);
     if (status == APR_SUCCESS) { 
         *accepted = csd;
-        apr_os_sock_get(&sockdes, csd);
-        if (sockdes >= FD_SETSIZE) {
-            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
-                         "new file descriptor %d is too large; you probably need "
-                         "to rebuild Apache with a larger FD_SETSIZE "
-                         "(currently %d)",
-                         sockdes, FD_SETSIZE);
-            apr_socket_close(csd);
-            return APR_EINTR;
-        } 
-#ifdef TPF
-        if (sockdes == 0) {                  /* 0 is invalid socket for TPF */
-            return APR_EINTR;
-        }
-#endif
-        return status;
+        return APR_SUCCESS;
     }
 
     if (APR_STATUS_IS_EINTR(status)) {
@@ -547,7 +549,7 @@ AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr,
              * occur in mobile IP.
              */
             ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
-                         "apr_accept: giving up.");
+                         "apr_socket_accept: giving up.");
             return APR_EGENERAL;
 #endif /*ENETDOWN*/
 
@@ -564,7 +566,7 @@ AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr,
 #else
         default:
             ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf,
-                         "apr_accept: (client socket)");
+                         "apr_socket_accept: (client socket)");
             return APR_EGENERAL;
 #endif
     }