blob: 03a86a08156a9d60ad41d0ff89b215ca994dddbe [file] [log] [blame]
#!/bin/sh
# Copyright 2016 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
JOB=$(basename "$0")
bootstat ui-post-stop
set +e
# shellcheck source=/dev/null
. /sbin/killers
# Terminate PKCS #11 services.
cryptohome --action=pkcs11_terminate
# Thaw any renderers that may have been left behind. If we
# have crashed while renderers are frozen, they'll be unkillable
# until we do this.
echo "THAWED" > "${CHROME_FREEZER_CGROUP_DIR:-}/to_be_frozen/freezer.state"
# Terminate any processes with files open on the mount point
# TODO(wad) parallelize with VFS/PID namespaces.
process_killer --session --file_holders
# Make sure everything is going down. No exceptions.
# The loop is so that clever daemons can't evade the kill by
# racing us and killing us first; we'll just try over and over
# until we win the race, and kill with pid -1 is atomic with
# respect to process creation.
while ! sudo -u chronos kill -9 -- -1 ; do
sleep .1
done
# Check for still-living chronos processes and log their status.
ps -u chronos --no-headers -o pid,stat,args |
logger -i -t "${JOB}-unkillable" -p crit
bootstat other-processes-terminated
# Android containers use run_oci to terminate and clean up containers. If
# run_oci exists, let run_oci perform the task first before falling back to
# general cleanup. Note that the cleanup is done here only when session_manager
# (e.g. crashes and) fails to kill/destroy the containers.
for container in /run/containers/*-run_oci ; do
# The '-run_oci' suffix above ensures that the run_oci commands below are
# executed only for containers started by run_oci. When run_oci is not
# installed in the rootfs, for example, these commands are never executed.
if [ -d "${container}" ]; then
run_oci --signal=KILL kill "${container##*/}"
NUM_RETRIES=3
for i in $(seq "${NUM_RETRIES}") ; do
# Both sleep and polling are needed here because 'run_oci destroy' fails
# if the container process is still alive.
sleep 1
run_oci destroy "${container##*/}" && break
if [ "${i}" = "${NUM_RETRIES}" ]; then
logger -i -p crit "Failed to destroy ${container##*/}"
fi
done
fi
done
# If there are any orphaned containers, they should also be cleaned up.
# This needs to be done prior to cryptohome unmounting so that there are no
# remaining processes with files open that would prevent a clean unmount.
for container in /run/containers/* ; do
if [ -d "${container}" ]; then
kill_with_open_files_on "${container##*/}" "${container}/root"
umount -R "${container}/root"
rm -rf "${container}"
fi
done
cryptohome --action=unmount
# Unmount the user session namespace mount point.
umount /run/namespaces/mnt_chrome
bootstat cryptohome-unmounted
# In case cryptohome crashes, application containers may remain active post
# cryptohome unmount. Check for the existence of these devices and lazy remove
# the encrypted containers of these containers.
for device in /dev/mapper/dmcrypt-* ; do
dmsetup remove --deferred "${device}"
done
# Post unmount, attempt to kill any left over processes from the session
# that could have leaked user mounts. This is intentionally done post
# unmount: lazy unmount cleans up mounts from the root namespace and
# newly launched processes will no be able to clone the mount.
process_killer --session --mount_holders