| #!/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 | |
| # 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 |