blob: ee4f588e9aa95a720761e47dd91d63b02ba2917d [file] [log] [blame]
#!/bin/sh
# Copyright 2018 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.
# Perform login tasks for shill. This script is called by the "login"
# init script.
# Shill expects to find a user profile in /run/shill/user_profiles. We
# link this path to the user profile in the user's cryptohome store so
# if shill restarts while the user is logged in, shill can regain access
# to the profile.
set -e
# The login init script calls this script with the login name of the
# user whose profile is being loaded.
user="$1"
script_name="$(basename "$0")"
profile_user="chronos"
profile_name="~${profile_user}/shill"
shill_state_root="/run/shill"
profile_link_root="${shill_state_root}/user_profiles"
profile_link_dir="${profile_link_root}/${profile_user}"
username_hash=""
if [ -z "${user}" ]; then
logger -t "${script_name}" "Unexpected empty user"
exit 1
fi
# We should not load multiple network profiles. If a profile link
# directory already exists, we should go no further.
if [ -e "${profile_link_dir}" ]; then
logger -t "${script_name}" "User already logged in; doing nothing."
exit 0
fi
system_path="$(cryptohome-path system "${user}")"
profile_base="/run/daemon-store/shill"
if [ ! -d "${profile_base}" ]; then
logger -t "${script_name}" \
"Daemon-store dir ${profile_base} does not exist"
exit 1
fi
username_hash="$(basename "${system_path}")"
profile_dir="${profile_base}/${username_hash}"
profile="${profile_dir}/shill.profile"
if [ ! -d "${profile_dir}" ]; then
if ! mkdir -p --mode=700 "${profile_dir}"; then
logger -t "${script_name}" \
"Failed to create shill user profile directory ${profile_dir}"
exit 1
fi
fi
# We need to ensure this dir (and files within it) are owned by shill:shill,
# regardless of whether we are creating it on this login or it already existed
# before now. By default, the 'chown -R' command does not follow symlinks, so
# there is no way shill can put a symlink in this dir as means of tricking the
# system into making other files owned by 'shill'. Also, this being the "shill
# user profile directory", it is fine to give shill ownership of all of its
# contents. Although 'chown -R' doesn't follow symlinks, it does affect bind
# mounts, so this code is only safe as long as shill runs without
# CAP_SYS_ADMIN. Ideally we should have some kind of test to make sure shill
# capabilities are never widened to include CAP_SYS_ADMIN -- filed
# crbug.com/869170 to track this issue in the general sense for CrOS system
# services.
if ! chown -R shill:shill "${profile_dir}"; then
logger -t "${script_name}" \
"Failed to chown shill user profile directory ${profile_dir}"
exit 1
fi
if ! mkdir -p --mode 0700 "${profile_link_root}"; then
logger -t "${script_name}" \
"Unable to create shill user profile link directory"
else
if ! chown shill:shill "${profile_link_root}"; then
logger -t "${script_name}" \
"Unable to chown shill user profile link directory"
fi
fi
ln -s "${profile_dir}" "${profile_link_dir}" ||
logger -t "${script_name}" \
"Failed to create shill user cryptohome link ${profile_link_dir}"
# We don't log here any more.
# TODO(crbug.com/1076094): remove this after M-86.
rm -rf "${profile_base}/shill_logs"
# wait_for_shill_dbus_services polls for the org.chromium.flimflam
# in the org.freedesktop.DBus.ListNames list that has all connected
# names on the Bus.
wait_for_shill_dbus_services() {
for _ in $(seq 1 15); do
if dbus-send --system --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus.ListNames |
grep -q '"org.chromium.flimflam"'; then
return 0
fi
sleep 0.2
done
}
# Technically, there's no guarantee that Shill has finished initializing
# before a login event happens. In practice, we don't experience that
# race unless Shill is actively crashing, but it does occur in tests
# (where we may intentionally restart Shill).
wait_for_shill_dbus_services
if [ ! -f "${profile}" ]; then
# If profile does not exist, ask shill to create one.
dbus-send --system --dest=org.chromium.flimflam --print-reply / \
org.chromium.flimflam.Manager.CreateProfile string:"${profile_name}" ||
logger -t "${script_name}" "Failed to create ${profile_name} profile"
fi
# Push user's network profile
dbus-send --system --dest=org.chromium.flimflam --print-reply / \
org.chromium.flimflam.Manager.InsertUserProfile \
string:"${profile_name}" string:"${username_hash}" ||
logger -t "${script_name}" "Failed to push ${profile_name} profile"