[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#822144: apache2: Race condition and logical error in apache2 SysV initscript



Package: apache2
Version: 2.4.10-10+deb8u4
Severity: important
Tags: patch

Jessie's apache2 SysV init script has two errors which can cause restarts to fail or cause problems on shutdown.


Issue 1: Race condition in do_stop() and apache_wait_stop()

The do_stop() functions issues an apache2ctl stop/graceful-stop (or a killproc) and calls apache_wait_stop() afterwards.
apache_wait_stop() tries to gather the current apache2 PID via pidofproc from the pid file and afterwards checks, if the
process has already terminated (via kill -0). This approach is problematic, because after receiving SIGTERM (via apache2ctl),
apache2 will remove its PID file in the shutdown process. When reaching the pidofproc invocation in apache_wait_stop(),
the PID file may have already been removed (by apache2) and the PID of the main apache process may not be determined
(although the process may yet be actively running). In this case, apache_wait_stop() will wrongly return with 0, indicating
that the process has been terminated successfully.
In most cases, this is not problematic, because the apache2 process will terminate shortly after - however in case of
restarts (which will call do_stop() -> do_start()) this may cause apache2 not being able to start up, because the old
main process is still active and holding resources (like sockets/ports or possibly locks etc.).

To resolve this, apache2ctl/killproc invocation should be done AFTER determining apaches main PID. Note that in Wheezys
initscripts, this race condition was not present - this has been introduced with Jessie.


Issue 2: Logical error in apache_wait_stop()

When waiting for the main PID to terminate, apache_wait_stop() will check every second, if the process is dead. This
is done for 60 seconds max, after that, the inner loop will break and presumably should set/return a statuscode of 2, which
it does not, because 'break' is executed before setting the correct return code:

if [ $i = '60' ]; then
  break
  STATUS=2
fi

This might cause problems in case apache2 cannot be shut down correctly (for whatever reason).


The following patch should fix the issues mentioned above:

--- apache2.init.org    2015-10-24 10:37:19.000000000 +0200
+++ apache2.init        2016-04-21 14:43:22.380946637 +0200
@@ -139,6 +139,7 @@

 apache_wait_stop() {
        local STATUS=$1
+       local METH=$2

        if [ $STATUS != 0 ] ; then
                return $STATUS
@@ -146,11 +147,18 @@

        PIDTMP=$(pidofproc -p $PIDFILE $DAEMON)
        if [ -n "${PIDTMP:-}" ] && kill -0 "${PIDTMP:-}" 2> /dev/null; then
+
+               if [ "$METH" = "kill" ]; then
+                       killproc -p $PIDFILE $DAEMON
+               else
+                       $APACHE2CTL $METH > /dev/null 2>&1
+               fi
+
                local i=0
                while kill -0 "${PIDTMP:-}" 2> /dev/null;  do
                        if [ $i = '60' ]; then
+                               STATUS=2
                                break
-                               STATUS=2
                        fi
                        [ "$VERBOSE" != no ] && log_progress_msg "."
                        sleep 1
@@ -223,15 +231,13 @@
        fi

        if [ $AP_RET = 2 ] && apache_conftest ; then
-               $APACHE2CTL $STOP > /dev/null 2>&1
-               apache_wait_stop $?
+               apache_wait_stop $? $STOP
                return $?
        else
                if [ $AP_RET = 2 ]; then
-                                       clear_error_msg
+                       clear_error_msg
                        APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX configtest failed, so we are trying to kill it manually. This is almost certainly suboptimal, so please make sure your system is working as you'd expect now!"
-                       killproc -p $PIDFILE $DAEMON
-                       apache_wait_stop $?
+                       apache_wait_stop $? "kill"
                        return $?
                elif [ $AP_RET = 1 ] ; then
                        APACHE2_INIT_MESSAGE="There are processes named 'apache2' running which do not match your pid file which are left untouched in the name of safety, Please review the situation by hand".


-- Package-specific info:

-- System Information:
Debian Release: 8.4
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.16.0-4-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages apache2 depends on:
ii  apache2-bin    2.4.10-10+deb8u4
ii  apache2-data   2.4.10-10+deb8u4
ii  apache2-utils  2.4.10-10+deb8u4
ii  dpkg           1.17.26
ii  lsb-base       4.1+Debian13+nmu1
ii  mime-support   3.58
ii  perl           5.20.2-3+deb8u4
ii  procps         2:3.3.9-9

Versions of packages apache2 recommends:
ii  ssl-cert  1.0.35

Versions of packages apache2 suggests:
pn  apache2-doc                                      <none>
pn  apache2-suexec-pristine | apache2-suexec-custom  <none>
pn  www-browser                                      <none>

Versions of packages apache2-bin depends on:
ii  libapr1                  1.5.1-3
ii  libaprutil1              1.5.4-1
ii  libaprutil1-dbd-sqlite3  1.5.4-1
ii  libaprutil1-ldap         1.5.4-1
ii  libc6                    2.19-18+deb8u4
ii  libldap-2.4-2            2.4.40+dfsg-1+deb8u2
ii  liblua5.1-0              5.1.5-7.1
ii  libpcre3                 2:8.35-3.3+deb8u4
ii  libssl1.0.0              1.0.1k-3+deb8u4
ii  libxml2                  2.9.1+dfsg1-5+deb8u1
ii  perl                     5.20.2-3+deb8u4
ii  zlib1g                   1:1.2.8.dfsg-2+b1

Versions of packages apache2-bin suggests:
pn  apache2-doc                                      <none>
pn  apache2-suexec-pristine | apache2-suexec-custom  <none>
pn  www-browser                                      <none>

Versions of packages apache2 is related to:
ii  apache2      2.4.10-10+deb8u4
ii  apache2-bin  2.4.10-10+deb8u4

-- no debconf information


Reply to: