blob: fa00f7d0531e43655fe03e9a6a5a1207addfe2e2 [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=./ui-killers-helper
. /usr/share/cros/init/ui-killers-helper
# 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"
# Start the dlcservice if it is not running.
status dlcservice | grep running || start dlcservice
# Get the list of user-tied DLC mount points for passing to the process_killer.
# Wait for the dlcservice to return a result. If timeout, meaning the dlcserivce
# is likely not availble, the DLC mount points list would be empty.
USER_TIED_DLC="$(dlcservice_util --list --user_tied --check_mount --timeout=5 |
jq -c '[.[][].root_mount]')"
# Terminate any processes with files open on the mount point
# TODO(wad) parallelize with VFS/PID namespaces.
process_killer --session --file_holders --mount_filter="${USER_TIED_DLC}"
# 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 ! minijail0 -u chronos -g chronos -G /bin/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
# Unload user-tied DLCs before cryptohome unmounting. Not waiting again for the
# service here since an attempt already made earlier to ensure dlcservice being
# available. Also set a short timeout for the command.
dlcservice_util --unload --user_tied --timeout=5 --nowait_for_service
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
# Clears chrome oobe storage files. Chrome could leave files behind for
# the sign-in storage partition. See http://b/277632606.
rm -rf /home/chronos/Default/Storage/ext/oobe
# 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