dgaudet     98/02/14 02:54:43

  Modified:    src      CHANGES
               src/main http_main.c
  Log:
  The addition of child_init_modules() and child_exit_modules() has made child
  initialization a critical section.  We can't service a USR1, TERM, or HUP
  request during this period because all our data structures could be in
  some unknown state.  So block_alarms() the whole way through.
  
  Fix a segfault caused by terminating before allocating pchild.  This won't
  occur with the above fix in place, but seems a reasonable precaution should
  there be a need to call clean_child_exit() before pchild is allocated.
  
  Fix various cases where exit() was called rather than clean_child_exit().
  
  Revision  Changes    Path
  1.630     +3 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.629
  retrieving revision 1.630
  diff -u -r1.629 -r1.630
  --- CHANGES   1998/02/14 03:26:56     1.629
  +++ CHANGES   1998/02/14 10:54:39     1.630
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3b6
   
  +  *) Cleaned up some race conditions in unix child_main during
  +     initialization. [Dean Gaudet]
  +
     *) SECURITY: "UserDir /abspath" without a * in the path would allow
        remote users to access "/~.." and bypass access restrictions
        (but note /~../.. was handled properly).
  
  
  
  1.288     +40 -22    apache-1.3/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/main/http_main.c,v
  retrieving revision 1.287
  retrieving revision 1.288
  diff -u -r1.287 -r1.288
  --- http_main.c       1998/02/14 10:43:20     1.287
  +++ http_main.c       1998/02/14 10:54:41     1.288
  @@ -320,6 +320,18 @@
   
   scoreboard *scoreboard_image = NULL;
   
  +static APACHE_TLS int volatile exit_after_unblock = 0;
  +
  +/* a clean exit from a child with proper cleanup */
  +static void __attribute__((noreturn)) clean_child_exit(int code)
  +{
  +    if (pchild) {
  +     child_exit_modules(pchild, server_conf);
  +     destroy_pool(pchild);
  +    }
  +    exit(code);
  +}
  +
   #if defined(USE_FCNTL_SERIALIZED_ACCEPT) || 
defined(USE_FLOCK_SERIALIZED_ACCEPT)
   static void expand_lock_fname(pool *p)
   {
  @@ -472,12 +484,12 @@
   
       if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
        perror("sigprocmask(SIG_BLOCK)");
  -     exit (1);
  +     clean_child_exit(1);
       }
       if ((err = pthread_mutex_lock(accept_mutex))) {
        errno = err;
        perror("pthread_mutex_lock");
  -     exit(1);
  +     clean_child_exit(1);
       }
       have_accept_mutex = 1;
   }
  @@ -489,7 +501,7 @@
       if ((err = pthread_mutex_unlock(accept_mutex))) {
        errno = err;
        perror("pthread_mutex_unlock");
  -     exit(1);
  +     clean_child_exit(1);
       }
       /* There is a slight race condition right here... if we were to die right
        * now, we'd do another pthread_mutex_unlock.  Now, doing that would let
  @@ -507,7 +519,7 @@
       have_accept_mutex = 0;
       if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
        perror("sigprocmask(SIG_SETMASK)");
  -     exit (1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -592,7 +604,7 @@
   {
       if (semop(sem_id, &op_on, 1) < 0) {
        perror("accept_mutex_on");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -600,7 +612,7 @@
   {
       if (semop(sem_id, &op_off, 1) < 0) {
        perror("accept_mutex_off");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -653,7 +665,7 @@
                    "fcntl: F_SETLKW: Error getting accept lock, exiting!  "
                    "Perhaps you need to use the LockFile directive to place "
                    "your lock file on a local disk!");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -669,7 +681,7 @@
                    "fcntl: F_SETLKW: Error freeing accept lock, exiting!  "
                    "Perhaps you need to use the LockFile directive to place "
                    "your lock file on a local disk!");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -693,7 +705,7 @@
       if (lock_fd == -1) {
        aplog_error(APLOG_MARK, APLOG_EMERG, server_conf,
                    "Child cannot open lock file: %s\n", lock_fname);
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -724,7 +736,7 @@
       if (ret < 0) {
        aplog_error(APLOG_MARK, APLOG_EMERG, server_conf,
                    "flock: LOCK_EX: Error getting accept lock. Exiting!");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -733,7 +745,7 @@
       if (flock(lock_fd, LOCK_UN) < 0) {
        aplog_error(APLOG_MARK, APLOG_EMERG, server_conf,
                    "flock: LOCK_UN: Error freeing accept lock. Exiting!");
  -     exit(1);
  +     clean_child_exit(1);
       }
   }
   
  @@ -789,15 +801,6 @@
   static APACHE_TLS const char *volatile timeout_name = NULL;
   static APACHE_TLS int volatile alarms_blocked = 0;
   static APACHE_TLS int volatile alarm_pending = 0;
  -static APACHE_TLS int volatile exit_after_unblock = 0;
  -
  -/* a clean exit from a child with proper cleanup */
  -static void __attribute__((noreturn)) clean_child_exit(int code)
  -{
  -    child_exit_modules(pchild, server_conf);
  -    destroy_pool(pchild);
  -    exit(code);
  -}
   
   void timeout(int sig)
   {                            /* Also called on SIGPIPE */
  @@ -1641,7 +1644,7 @@
       if (scoreboard_fd == -1) {
        perror(scoreboard_fname);
        fprintf(stderr, "Cannot open scoreboard file:\n");
  -     exit(1);
  +     clean_child_exit(1);
       }
   #else
   #ifdef __EMX__
  @@ -2905,6 +2908,18 @@
       struct sockaddr sa_client;
       listen_rec *lr;
   
  +    /* All of initialization is a critical section, we don't care if we're
  +     * told to HUP or USR1 before we're done initializing.  For example,
  +     * we could be half way through child_init_modules() when a restart
  +     * signal arrives, and we'd have no real way to recover gracefully
  +     * and exit properly.
  +     *
  +     * I suppose a module could take forever to initialize, but that would
  +     * be either a broken module, or a broken configuration (i.e. network
  +     * problems, file locking problems, whatever). -djg
  +     */
  +    block_alarms();
  +
       my_pid = getpid();
       csd = -1;
       dupped_csd = -1;
  @@ -2938,7 +2953,7 @@
       if (!geteuid() && setuid(user_id) == -1) {
        aplog_error(APLOG_MARK, APLOG_ALERT, server_conf,
                    "setuid: unable to change uid");
  -     exit(1);
  +     clean_child_exit(1);
       }
   #endif
   
  @@ -2966,6 +2981,9 @@
           DosSetSignalExceptionFocus(0, &ulTimes);
       }
   #endif
  +
  +    /* done with the initialization critical section */
  +    unblock_alarms();
   
       while (1) {
        BUFF *conn_io;
  
  
  

Reply via email to