blob: ddd2f43ede82f411987ab16282a3b9d163a23886 [file] [log] [blame]
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
description "Mount the MyFiles directory using mount-passthrough."
author "chromium-os-dev@chromium.org"
start on starting arcvm-post-login-services
stop on stopping arcvm-post-login-services
# Do not allow OOM killer to terminate this job since it will break file
# sharing support (which e.g. our Photos app relies on) until ARCVM restarts.
# TODO(b/164939771): Choose a better OOM score which guarantees the Chrome
# browser process is always terminated before this one.
oom score never
# VmHWM of the process is ~6 MB in the steady state, and setting the VM size
# soft limit below that results in process termination. On the other hand,
# VmPeak points to somewhat higher value (~200 MB), and if we specify a soft
# limit lower than that, while not causing process termination, it results in
# memory allocation errors for actions like `ls` command.
# Given that, we choose to set a high value of 1 GB as the soft limit here.
# TODO(b/164936284): Specify a lower limit after improving mount-passthrough.
limit as 1000000000 unlimited
expect fork
import CHROMEOS_USER_ID_HASH
env SOURCE=/home/chronos/user/MyFiles
env DEST=/run/arcvm/media/MyFiles
env UMASK=007
env ANDROID_ROOT_UID=0
env ANDROID_EXTERNAL_STORAGE_GID=1077
pre-start script
# When vm_concierge starts before login, <cryptohome>/mount/user is not
# mounted on /home/chronos/user in the concierge namespace. In this case
# we need to properly set up /home/chronos/user/MyFiles (and
# /home/chronos/user/MyFiles/Downloads) in the namespace.
if ! nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mountpoint -q /home/chronos/user; then
# Check whether the imported Chrome OS user id hash is a valid one.
if ! echo "${CHROMEOS_USER_ID_HASH}" | grep -q -E '^[0-9a-f]{40,}$'; then
logger -t "${UPSTART_JOB}" "Invalid user id hash ${CHROMEOS_USER_ID_HASH}"
exit 1
fi
CRYPTOHOME_USER_DIR="/home/.shadow/${CHROMEOS_USER_ID_HASH}/mount/user"
# Check whether the MyFiles directory resides in cryptohome.
CRYPTOHOME_MYFILES_DIR="${CRYPTOHOME_USER_DIR}/MyFiles"
if [ ! -d "${CRYPTOHOME_MYFILES_DIR}" ]; then
logger -t "${UPSTART_JOB}" \
"MyFiles directory ${CRYPTOHOME_MYFILES_DIR} does not exist"
exit 1
fi
# Mount /home/chronos/user/MyFiles.
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mkdir -p "${SOURCE}"
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mount --bind "${CRYPTOHOME_MYFILES_DIR}" "${SOURCE}"
# Bind-mount the Downloads directory on /home/chronos/user/MyFiles/Downloads
# in the concierge namespace if it is bind-mounted in the init namespace.
if mountpoint -q "${SOURCE}/Downloads"; then
# Check whether the Downloads directory resides in cryptohome.
CRYPTOHOME_DOWNLOADS_DIR="${CRYPTOHOME_USER_DIR}/Downloads"
if [ ! -d "${CRYPTOHOME_DOWNLOADS_DIR}" ]; then
logger -t "${UPSTART_JOB}" \
"Downloads directory ${CRYPTOHOME_DOWNLOADS_DIR} does not exist"
exit 1
fi
# Mount /home/chronos/user/MyFiles/Downloads.
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mkdir -p "${SOURCE}/Downloads"
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mount --bind "${CRYPTOHOME_DOWNLOADS_DIR}" "${SOURCE}/Downloads"
fi
fi
# Create the destination directory.
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- mkdir -p "${DEST}"
end script
exec nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- /usr/sbin/syslog-cat --identifier="${UPSTART_JOB}" -- \
mount-passthrough-jailed "${SOURCE}" "${DEST}" "${UMASK}" \
"${ANDROID_ROOT_UID}" "${ANDROID_EXTERNAL_STORAGE_GID}" "full"
post-stop script
# ${DEST} is not automatically unmounted when terminated by SIGKILL.
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- umount "${DEST}" || true
# ${SOURCE} is not unmounted anywhere, so we should take care of it too.
nsenter --mount=/run/namespaces/mnt_concierge --no-fork \
-- umount -R "${SOURCE}" || true
end script