Commit 4b5381be authored by Yuwei Huang's avatar Yuwei Huang Committed by Commit Bot

[remoting][mac] Replace host service script with the binary

This CL removes the no longer used host service script and updates
installer and other plist to use the new script.

Locally tested both fresh install and upgrade from M78 host and both
scenarios work.

Bug: 1013692, 10142116
Change-Id: If59e6a16fd1c3f86bfb76ddb5fbf850874d389a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1863735Reviewed-by: default avatarLambros Lambrou <lambroslambrou@chromium.org>
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706203}
parent 2f2cb363
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
</array> </array>
<key>ProgramArguments</key> <key>ProgramArguments</key>
<array> <array>
<string>/Library/PrivilegedHelperTools/@@HOST_BUNDLE_NAME@@/Contents/MacOS/host_service</string> <string>/Library/PrivilegedHelperTools/@@HOST_BUNDLE_NAME@@/Contents/MacOS/remoting_me2me_host_service</string>
<string>--run-from-launchd</string> <string>--run-from-launchd</string>
</array> </array>
<key>RunAtLoad</key> <key>RunAtLoad</key>
......
...@@ -9,15 +9,16 @@ ...@@ -9,15 +9,16 @@
HELPERTOOLS=/Library/PrivilegedHelperTools HELPERTOOLS=/Library/PrivilegedHelperTools
SERVICE_NAME=org.chromium.chromoting SERVICE_NAME=org.chromium.chromoting
CONFIG_FILE="$HELPERTOOLS/$SERVICE_NAME.json" CONFIG_FILE="$HELPERTOOLS/$SERVICE_NAME.json"
SCRIPT_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me.sh" OLD_SCRIPT_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me.sh"
USERS_TMP_FILE="$SCRIPT_FILE.users"
PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist
PAM_CONFIG=/etc/pam.d/chrome-remote-desktop PAM_CONFIG=/etc/pam.d/chrome-remote-desktop
ENABLED_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me_enabled" ENABLED_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me_enabled"
ENABLED_FILE_BACKUP="$ENABLED_FILE.backup" ENABLED_FILE_BACKUP="$ENABLED_FILE.backup"
HOST_BUNDLE_NAME=@@HOST_BUNDLE_NAME@@ HOST_BUNDLE_NAME=@@HOST_BUNDLE_NAME@@
HOST_SERVICE_BINARY="$HELPERTOOLS/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host_service"
HOST_LEGACY_BUNDLE_NAME=@@HOST_LEGACY_BUNDLE_NAME@@ HOST_LEGACY_BUNDLE_NAME=@@HOST_LEGACY_BUNDLE_NAME@@
HOST_EXE="$HELPERTOOLS/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host" HOST_EXE="$HELPERTOOLS/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host"
USERS_TMP_FILE="$HOST_SERVICE_BINARY.users"
KSADMIN=/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin KSADMIN=/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin
KSUPDATE=https://tools.google.com/service/update2 KSUPDATE=https://tools.google.com/service/update2
...@@ -67,12 +68,10 @@ if [[ -f "$ENABLED_FILE_BACKUP" ]]; then ...@@ -67,12 +68,10 @@ if [[ -f "$ENABLED_FILE_BACKUP" ]]; then
mv "$ENABLED_FILE_BACKUP" "$ENABLED_FILE" mv "$ENABLED_FILE_BACKUP" "$ENABLED_FILE"
fi fi
# If there is a backup plist, restore it in order to use the old launchd # If there is a backup script, restore it.
# service script instead of the new one. if [[ -f "$INSTALLER_TEMP/script_backup" ]]; then
if [[ -f "$INSTALLER_TEMP/plist_backup" ]]; then logger Restoring original launchd script
logger Restoring original launchd agent mv "$INSTALLER_TEMP/script_backup" "$OLD_SCRIPT_FILE"
mv "$INSTALLER_TEMP/plist_backup" "$PLIST"
mv "$INSTALLER_TEMP/script_backup" "$SCRIPT_FILE"
fi fi
# Create the PAM configuration unless it already exists and has been edited. # Create the PAM configuration unless it already exists and has been edited.
......
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
HELPERTOOLS=/Library/PrivilegedHelperTools HELPERTOOLS=/Library/PrivilegedHelperTools
SERVICE_NAME=org.chromium.chromoting SERVICE_NAME=org.chromium.chromoting
HOST_BUNDLE_NAME=@@HOST_BUNDLE_NAME@@
CONFIG_FILE="$HELPERTOOLS/$SERVICE_NAME.json" CONFIG_FILE="$HELPERTOOLS/$SERVICE_NAME.json"
SCRIPT_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me.sh" OLD_SCRIPT_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me.sh"
USERS_TMP_FILE="$SCRIPT_FILE.users" HOST_SERVICE_BINARY="$HELPERTOOLS/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host_service"
USERS_TMP_FILE="$HOST_SERVICE_BINARY.users"
PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist PLIST=/Library/LaunchAgents/org.chromium.chromoting.plist
ENABLED_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me_enabled" ENABLED_FILE="$HELPERTOOLS/$SERVICE_NAME.me2me_enabled"
ENABLED_FILE_BACKUP="$ENABLED_FILE.backup" ENABLED_FILE_BACKUP="$ENABLED_FILE.backup"
...@@ -24,10 +26,14 @@ function on_error { ...@@ -24,10 +26,14 @@ function on_error {
} }
function find_users_with_active_hosts { function find_users_with_active_hosts {
ps -eo uid,command | awk -v script="$SCRIPT_FILE" ' # User might be running the old script, the new service binary, or both in
$2 == "/bin/sh" && $3 == script && $4 == "--run-from-launchd" { # some cases, so we need to find both processes then dedup the uid.
print $1 ps -eo uid,command |
}' awk -v script="$OLD_SCRIPT_FILE" -v binary="$HOST_SERVICE_BINARY" '
($2 == "/bin/sh" && $3 == script && $4 == "--run-from-launchd") ||
($2 == binary && $3 == "--run-from-launchd") {
print $1
}' | sort | uniq
} }
function find_login_window_for_user { function find_login_window_for_user {
...@@ -63,16 +69,14 @@ if [[ -f "$ENABLED_FILE" ]]; then ...@@ -63,16 +69,14 @@ if [[ -f "$ENABLED_FILE" ]]; then
mv "$ENABLED_FILE" "$ENABLED_FILE_BACKUP" mv "$ENABLED_FILE" "$ENABLED_FILE_BACKUP"
fi fi
# If there is an old launchd script, create a backup of the system's launchd # If there is an old launchd script, create a backup of it, so that the
# agent plist, so that the postflight script can restore it. This ensures the # postflight script can restore it. This ensures the new host service falls back
# old launchd script gets used instead of the new one in the host bundle. # to the old launchd script when it is available on Mojave.
# The script also needs to be backed up and restored, as the new package does # The script needs to be backed up and restored, as the new package does not
# not provide it, and the installer deletes it from the system. # provide it, and the installer deletes it from the system.
# TODO(lambroslambrou): Remove this after users have authorized the new script. if [[ -f "$OLD_SCRIPT_FILE" ]]; then
if [[ -f "$SCRIPT_FILE" ]]; then
logger Backing up launchd agent logger Backing up launchd agent
cp "$PLIST" "$INSTALLER_TEMP/plist_backup" cp "$OLD_SCRIPT_FILE" "$INSTALLER_TEMP/script_backup"
cp "$SCRIPT_FILE" "$INSTALLER_TEMP/script_backup"
fi fi
# Stop and unload the service for each user currently running the service, and # Stop and unload the service for each user currently running the service, and
......
...@@ -40,7 +40,7 @@ setup() { ...@@ -40,7 +40,7 @@ setup() {
# Binaries/bundles to sign. # Binaries/bundles to sign.
ME2ME_HOST="PrivilegedHelperTools/${HOST_BUNDLE_NAME}" ME2ME_HOST="PrivilegedHelperTools/${HOST_BUNDLE_NAME}"
ME2ME_EXE_DIR="${ME2ME_HOST}/Contents/MacOS/" ME2ME_EXE_DIR="${ME2ME_HOST}/Contents/MacOS/"
ME2ME_LAUNCHD_SERVICE="${ME2ME_EXE_DIR}/host_service" ME2ME_LAUNCHD_SERVICE="${ME2ME_EXE_DIR}/remoting_me2me_host_service"
ME2ME_NM_HOST="${ME2ME_EXE_DIR}/${NATIVE_MESSAGING_HOST_BUNDLE_NAME}/" ME2ME_NM_HOST="${ME2ME_EXE_DIR}/${NATIVE_MESSAGING_HOST_BUNDLE_NAME}/"
IT2ME_NM_HOST="${ME2ME_EXE_DIR}/${REMOTE_ASSISTANCE_HOST_BUNDLE_NAME}/" IT2ME_NM_HOST="${ME2ME_EXE_DIR}/${REMOTE_ASSISTANCE_HOST_BUNDLE_NAME}/"
UNINSTALLER="Applications/${HOST_UNINSTALLER_NAME}.app" UNINSTALLER="Applications/${HOST_UNINSTALLER_NAME}.app"
......
...@@ -133,15 +133,10 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -133,15 +133,10 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
[self shutdownService]; [self shutdownService];
// Remove the old helper script if it exists. The new helper script is part
// of the host bundle.
const char kOldHostHelperScriptPath[] =
"/Library/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh";
[self sudoDelete:remoting::kServicePlistPath usingAuth:authRef]; [self sudoDelete:remoting::kServicePlistPath usingAuth:authRef];
[self sudoDelete:remoting::kHostBinaryPath usingAuth:authRef]; [self sudoDelete:remoting::kHostBinaryPath usingAuth:authRef];
[self sudoDelete:remoting::kHostLegacyBinaryPath usingAuth:authRef]; [self sudoDelete:remoting::kHostLegacyBinaryPath usingAuth:authRef];
[self sudoDelete:kOldHostHelperScriptPath usingAuth:authRef]; [self sudoDelete:remoting::kOldHostHelperScriptPath usingAuth:authRef];
[self sudoDelete:remoting::kHostConfigFilePath usingAuth:authRef]; [self sudoDelete:remoting::kHostConfigFilePath usingAuth:authRef];
[self sudoDelete:remoting::kLogFilePath usingAuth:authRef]; [self sudoDelete:remoting::kLogFilePath usingAuth:authRef];
[self sudoDelete:remoting::kLogFileConfigPath usingAuth:authRef]; [self sudoDelete:remoting::kLogFileConfigPath usingAuth:authRef];
......
...@@ -80,15 +80,6 @@ bundle_data("remoting_host_resources") { ...@@ -80,15 +80,6 @@ bundle_data("remoting_host_resources") {
} }
} }
bundle_data("remoting_me2me_script") {
sources = [
"host_service",
]
outputs = [
"{{bundle_executable_dir}}/{{source_file_part}}",
]
}
target("mac_app_bundle", "remoting_me2me_host") { target("mac_app_bundle", "remoting_me2me_host") {
extra_configs = [ "//remoting/build/config:version" ] extra_configs = [ "//remoting/build/config:version" ]
info_plist = "remoting_me2me_host-Info.plist" info_plist = "remoting_me2me_host-Info.plist"
...@@ -125,8 +116,7 @@ target("mac_app_bundle", "remoting_me2me_host") { ...@@ -125,8 +116,7 @@ target("mac_app_bundle", "remoting_me2me_host") {
} }
deps += [ deps += [
":remoting_host_resources", ":remoting_host_resources",
#":remoting_me2me_host_service_bundle_data", ":remoting_me2me_host_service_bundle_data",
":remoting_me2me_script",
"//remoting/host:remoting_infoplist_strings", "//remoting/host:remoting_infoplist_strings",
"//remoting/resources:copy_locales", "//remoting/resources:copy_locales",
] ]
......
...@@ -21,8 +21,8 @@ const char kServiceName[] = SERVICE_NAME; ...@@ -21,8 +21,8 @@ const char kServiceName[] = SERVICE_NAME;
const char kHostConfigFileName[] = SERVICE_NAME ".json"; const char kHostConfigFileName[] = SERVICE_NAME ".json";
const char kHostConfigFilePath[] = HELPER_TOOLS_DIR SERVICE_NAME ".json"; const char kHostConfigFilePath[] = HELPER_TOOLS_DIR SERVICE_NAME ".json";
const char kHostHelperScriptPath[] = const char kHostServiceBinaryPath[] = HELPER_TOOLS_DIR HOST_BUNDLE_NAME
HELPER_TOOLS_DIR HOST_BUNDLE_NAME "/Contents/MacOS/host_service"; "/Contents/MacOS/remoting_me2me_host_service";
const char kOldHostHelperScriptPath[] = const char kOldHostHelperScriptPath[] =
HELPER_TOOLS_DIR SERVICE_NAME ".me2me.sh"; HELPER_TOOLS_DIR SERVICE_NAME ".me2me.sh";
const char kHostBinaryPath[] = HELPER_TOOLS_DIR HOST_BUNDLE_NAME; const char kHostBinaryPath[] = HELPER_TOOLS_DIR HOST_BUNDLE_NAME;
......
...@@ -21,7 +21,7 @@ extern const char kHostConfigFilePath[]; ...@@ -21,7 +21,7 @@ extern const char kHostConfigFilePath[];
// service. // service.
// It is also used (as non-root) to provide version information for the // It is also used (as non-root) to provide version information for the
// installed host components. // installed host components.
extern const char kHostHelperScriptPath[]; extern const char kHostServiceBinaryPath[];
// Path to the old host helper script, which is still used after user updates // Path to the old host helper script, which is still used after user updates
// their host on macOS 10.14.*. // their host on macOS 10.14.*.
......
#!/bin/sh
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
NAME=org.chromium.chromoting
SCRIPT_DIR="$(dirname "${0}")"
CONFIG_DIR=/Library/PrivilegedHelperTools
ENABLED_FILE="$CONFIG_DIR/$NAME.me2me_enabled"
CONFIG_FILE="$CONFIG_DIR/$NAME.json"
HOST_EXE="$SCRIPT_DIR/remoting_me2me_host"
PLIST_FILE="$SCRIPT_DIR/../Info.plist"
# The exit code returned by 'wait' when a process is terminated by SIGTERM.
SIGTERM_EXIT_CODE=143
# Range of exit codes returned by the host to indicate that a permanent error
# has occurred and that the host should not be restarted. Please, keep these
# constants in sync with remoting/host/host_exit_codes.h.
MIN_PERMANENT_ERROR_EXIT_CODE=100
MAX_PERMANENT_ERROR_EXIT_CODE=105
# Constants controlling the host process relaunch throttling.
MINIMUM_RELAUNCH_INTERVAL=60
MAXIMUM_HOST_FAILURES=10
# Exit code 126 is defined by Posix to mean "Command found, but not
# executable", and is returned if the process cannot be launched due to
# parental control.
PERMISSION_DENIED_PARENTAL_CONTROL=126
HOST_PID=0
SIGNAL_WAS_TRAPPED=0
# This script works as a proxy between launchd and the host. Signals of
# interest to the host must be forwarded.
SIGNAL_LIST="SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABRT SIGEMT \
SIGFPE SIGKILL SIGBUS SIGSEGV SIGSYS SIGPIPE SIGALRM SIGTERM SIGURG \
SIGSTOP SIGTSTP SIGCONT SIGCHLD SIGTTIN SIGTTOU SIGIO SIGXCPU SIGXFSZ \
SIGVTALRM SIGPROF SIGWINCH SIGINFO SIGUSR1 SIGUSR2"
handle_signal() {
SIGNAL_WAS_TRAPPED=1
}
run_host() {
# Run the config-upgrade tool, but only if running as root, as normal users
# don't have permission to write the config file.
if [[ "$EUID" -eq 0 ]]; then
"$HOST_EXE" --upgrade-token --host-config="$CONFIG_FILE"
fi
local host_failure_count=0
local host_start_time=0
while true; do
if [[ ! -f "$ENABLED_FILE" ]]; then
echo "Daemon is disabled."
exit 0
fi
# If this is not the first time the host has run, make sure we don't
# relaunch it too soon.
if [[ "$host_start_time" -gt 0 ]]; then
local host_lifetime=$(($(date +%s) - $host_start_time))
echo "Host ran for ${host_lifetime}s"
if [[ "$host_lifetime" -lt "$MINIMUM_RELAUNCH_INTERVAL" ]]; then
# If the host didn't run for very long, assume it crashed. Relaunch only
# after a suitable delay and increase the failure count.
host_failure_count=$(($host_failure_count + 1))
echo "Host failure count $host_failure_count/$MAXIMUM_HOST_FAILURES"
if [[ "$host_failure_count" -ge "$MAXIMUM_HOST_FAILURES" ]]; then
echo "Too many host failures. Giving up."
exit 1
fi
local relaunch_in=$(($MINIMUM_RELAUNCH_INTERVAL - $host_lifetime))
echo "Relaunching in ${relaunch_in}s"
sleep "$relaunch_in"
else
# If the host ran for long enough, reset the crash counter.
host_failure_count=0
fi
fi
# Execute the host asynchronously and forward signals to it.
trap "handle_signal" $SIGNAL_LIST
host_start_time=$(date +%s)
"$HOST_EXE" --host-config="$CONFIG_FILE" \
--ssh-auth-sockname="/tmp/chromoting.$USER.ssh_auth_sock" &
HOST_PID="$!"
# Wait for the host to return and process its exit code.
while true; do
wait "$HOST_PID"
EXIT_CODE="$?"
if [[ $SIGNAL_WAS_TRAPPED -eq 1 ]]; then
# 'wait' returned as the result of a trapped signal and the exit code is
# the signal that was trapped + 128. Forward the signal to the host.
SIGNAL_WAS_TRAPPED=0
local SIGNAL=$(($EXIT_CODE - 128))
echo "Forwarding signal $SIGNAL to host"
kill -$SIGNAL "$HOST_PID"
elif [[ "$EXIT_CODE" -eq "0" ||
"$EXIT_CODE" -eq "$SIGTERM_EXIT_CODE" ||
"$EXIT_CODE" -eq "$PERMISSION_DENIED_PARENTAL_CONTROL" ||
("$EXIT_CODE" -ge "$MIN_PERMANENT_ERROR_EXIT_CODE" && \
"$EXIT_CODE" -le "$MAX_PERMANENT_ERROR_EXIT_CODE") ]]; then
echo "Host returned permanent exit code $EXIT_CODE at ""$(date)"""
if [[ "$EXIT_CODE" -eq 101 ]]; then
# Exit code 101 is "hostID deleted", which indicates that the host
# was taken off-line remotely. To prevent the host being restarted
# when the login context changes, try to delete the "enabled" file.
# Since this requires root privileges, this is only possible when
# this script is launched in the "login" context. In the "aqua"
# context, just exit and try again next time.
echo "Host id deleted - disabling"
rm -f "$ENABLED_FILE" 2>/dev/null
fi
exit "$EXIT_CODE"
else
# Ignore non-permanent error-code and launch host again. Stop handling
# signals temporarily in case the script has to sleep to throttle host
# relaunches. While throttling, there is no host process to which to
# forward the signal, so the default behaviour should be restored.
echo "Host returned non-permanent exit code $EXIT_CODE at ""$(date)"""
trap - $SIGNAL_LIST
HOST_PID=0
break
fi
done
done
}
if [[ "$1" = "--disable" ]]; then
# This script is executed from base::mac::ExecuteWithPrivilegesAndWait(),
# which requires the child process to write its PID to stdout before
# anythine else. See base/mac/authorization_util.h for details.
echo $$
rm -f "$ENABLED_FILE"
elif [[ "$1" = "--enable" ]]; then
echo $$
# Ensure the config file is private whilst being written.
rm -f "$CONFIG_FILE"
umask 0077
cat > "$CONFIG_FILE"
# Ensure the config is readable by the user registering the host.
chmod +a "$USER:allow:read" "$CONFIG_FILE"
touch "$ENABLED_FILE"
elif [[ "$1" = "--save-config" ]]; then
echo $$
cat > "$CONFIG_FILE"
elif [[ "$1" = "--host-version" ]]; then
/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PLIST_FILE"
elif [[ "$1" = "--run-from-launchd" ]]; then
echo Host started for user $USER at $"$(date)"
run_host
else
echo $$
exit 1
fi
...@@ -23,7 +23,7 @@ constexpr int kMinDialogWidthPx = 650; ...@@ -23,7 +23,7 @@ constexpr int kMinDialogWidthPx = 650;
// The name of the host service as it appears in the system's Accessibility // The name of the host service as it appears in the system's Accessibility
// permission dialog. // permission dialog.
constexpr NSString* kHostServiceName = @"remoting_me2me_host"; constexpr NSString* kHostServiceName = @"ChromeRemoteDesktopHost";
void ShowPermissionDialog() { void ShowPermissionDialog() {
base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]); base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
......
...@@ -94,7 +94,7 @@ bool RunHelperAsRoot(const std::string& command, ...@@ -94,7 +94,7 @@ bool RunHelperAsRoot(const std::string& command,
FILE* pipe = nullptr; FILE* pipe = nullptr;
pid_t pid; pid_t pid;
OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID(
authorization.get(), remoting::kHostHelperScriptPath, authorization.get(), remoting::kHostServiceBinaryPath,
kAuthorizationFlagDefaults, arguments, &pipe, &pid); kAuthorizationFlagDefaults, arguments, &pipe, &pid);
if (status != errAuthorizationSuccess) { if (status != errAuthorizationSuccess) {
LOG(ERROR) << "AuthorizationExecuteWithPrivileges: " LOG(ERROR) << "AuthorizationExecuteWithPrivileges: "
...@@ -150,7 +150,7 @@ bool RunHelperAsRoot(const std::string& command, ...@@ -150,7 +150,7 @@ bool RunHelperAsRoot(const std::string& command,
return true; return true;
} }
LOG(ERROR) << remoting::kHostHelperScriptPath << " failed with exit status " LOG(ERROR) << remoting::kHostServiceBinaryPath << " failed with exit status "
<< exit_status; << exit_status;
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment