shill: Add new init script for sandboxing kill switch

We have a feature flag in Chrome (called ShillSandboxing) that
will control whether shill is run in a minijail sandbox. Add an Upstart
init job that queries Chrome for this policy and writes a file
accordingly that can be accessed upon next boot. This init job will
start on the "started system-services" Upstart event, which assures
that Chrome is running but doesn't require the user/guest to have logged
in.

CQ-DEPEND=CL:1176106,CL:1173260,CL:1204652
BUG=chromium:649417
TEST=disable/enable ShillSandboxing Chrome feature flag (through
/etc/chrome_dev.conf on DUT) and see shill running as root/non-root
Change-Id: I45a665561b8809f8cbef42a09d6cd35884f0bfe7
Reviewed-on: https://chromium-review.googlesource.com/1176166
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Micah Morton <mortonm@chromium.org>
Reviewed-by: Brian Norris <briannorris@chromium.org>
diff --git a/init/shill-sandboxing-kill-switch.conf b/init/shill-sandboxing-kill-switch.conf
new file mode 100644
index 0000000..0afc5e5
--- /dev/null
+++ b/init/shill-sandboxing-kill-switch.conf
@@ -0,0 +1,56 @@
+#
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+#
+# Micah Morton <mortonm@chromium.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+
+description     "Write kill switch file for sandboxing shill."
+author          "chromium-os-dev@chromium.org"
+
+# NOTE: Since Chrome feature flags only get updated through Finch during
+# browser startup, we need to relay the message from Chrome to shill whenever
+# the ShillSandboxing flag is disabled. We do this by writing a file in
+# /var/lib/shill that is queried by the shill.sh init script next time shill
+# spawns. In this way, after updating Finch server configs (and waiting the
+# necessary time to push configs to clients), going from shill sandboxing
+# enabled to disabled requires first a reboot (which will trigger this script
+# under the updated feature flag, since Chrome has been restarted by the
+# reboot) followed by restarting shill (e.g. another reboot or "restart shill"
+# command).
+
+# Use 'start on started system-services' to ensure Chrome is running and we can
+# query the "IsShillSandboxingEnabled" feature flag.
+# TODO(mortonm): Remove this file completely when removing the kill switch for
+# shill sandboxing.
+start on started system-services
+
+pre-start exec mkdir -p /var/lib/shill
+
+script
+  status=0
+  reply=$(minijail0 -u chronos /usr/bin/dbus-send --system --type=method_call \
+    --print-reply \
+    --dest=org.chromium.ChromeFeaturesService \
+    /org/chromium/ChromeFeaturesService \
+    "org.chromium.ChromeFeaturesServiceInterface.IsShillSandboxingEnabled" \
+    2>/dev/null) || status=$?
+  if [ ${status} -eq 0 -a "${reply##* }" = "false" ] ; then
+    # Disable sandboxing.
+    echo "1" > /var/lib/shill/shill_sandboxing_disabled
+  else
+    # Either "${reply##* }" equals "true" or something went wrong in parsing
+    # response. Regardless, remove the file that disables sandboxing since
+    # shill running in a sandbox is the default/expected behavior.
+    rm -f /var/lib/shill/shill_sandboxing_disabled
+  fi
+end script
diff --git a/init/shill.sh b/init/shill.sh
index ef5a328..3fb2e10 100644
--- a/init/shill.sh
+++ b/init/shill.sh
@@ -61,14 +61,18 @@
   ARGS="${ARGS} --portal-list="
 fi
 
-ARGS="${ARGS} --jail-vpn-clients"
-# Run shill as shill user/group in a minijail:
-#   -G so shill programs can inherit supplementary groups.
-#   -n to run shill with no_new_privs.
-#   -B 20 to avoid locking SECURE_KEEP_CAPS flag.
-#   -c for runtime capabilities:
-#     CAP_WAKE_ALARM | CAP_NET_RAW | CAP_NET_ADMIN | CAP_NET_BROADCAST |
-#     CAP_NET_BIND_SERVICE | CAP_SETPCAP | CAP_SETUID | CAP_SETGID | CAP_KILL
-#   --ambient so child processes can inherit runtime capabilities:
-exec /sbin/minijail0 -u shill -g shill -G -n -B 20 -c 800003de0 --ambient \
-     -- /usr/bin/shill ${ARGS}
+if [ -e /var/lib/shill/shill_sandboxing_disabled ]; then
+  exec /usr/bin/shill ${ARGS}
+else
+  ARGS="${ARGS} --jail-vpn-clients"
+  # Run shill as shill user/group in a minijail:
+  #   -G so shill programs can inherit supplementary groups.
+  #   -n to run shill with no_new_privs.
+  #   -B 20 to avoid locking SECURE_KEEP_CAPS flag.
+  #   -c for runtime capabilities:
+  #     CAP_WAKE_ALARM | CAP_NET_RAW | CAP_NET_ADMIN | CAP_NET_BROADCAST |
+  #     CAP_NET_BIND_SERVICE | CAP_SETPCAP | CAP_SETUID | CAP_SETGID | CAP_KILL
+  #   --ambient so child processes can inherit runtime capabilities:
+  exec /sbin/minijail0 -u shill -g shill -G -n -B 20 -c 800003de0 --ambient \
+       -- /usr/bin/shill ${ARGS}
+fi