cros_sdk: mount cgroups in main mount namespace

When we moved to unshare, it implicitly setup cgroups inside of that
mount namespace.  That's not what we want -- we need to be setup in
the main namespace so that it only gets mounted once and the parent
process gets access to it so it can kill cros_sdk if need be.

Have the re-exec logic be a bit fancier.  If we are non-root, and we
have yet to setup cgroups, just re-exec ourselves with sudo.  Then
this root process can mount cgroups before re-execing again in a new
mount namespace.

If cgroups are already setup, then skip that and just unshare directly
like we are today.  There's more overhead on the first exec, but it's
unchanged after that, so the common case should be OK.

BUG=chromium-os:36327
TEST=`cros_sdk -- true` leaves cgroup mounts behind and only mounts on first try

Change-Id: I87368498016ee329674b5d3ce934ed6eeae82040
Reviewed-on: https://gerrit.chromium.org/gerrit/38375
Reviewed-by: David James <davidjames@chromium.org>
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/scripts/cros_sdk.py b/scripts/cros_sdk.py
index b19beb3..0b916b7 100644
--- a/scripts/cros_sdk.py
+++ b/scripts/cros_sdk.py
@@ -207,15 +207,22 @@
   return cmd
 
 
-def _ReExecuteAsRootIfNeeded(argv):
+def _ReExecuteIfNeeded(argv):
   """Re-execute cros_sdk as root.
 
   Also unshare the mount namespace so as to ensure that processes outside
   the chroot can't mess with our mounts.
   """
+  MAGIC_VAR = '%CROS_SDK_MOUNT_NS'
   if os.geteuid() != 0:
-    cmd = _SudoCommand()
-    os.execvp(cmd[0], cmd + ['--', 'unshare', '-m', '--'] + argv)
+    cmd = _SudoCommand() + ['--'] + argv
+    os.execvp(cmd[0], cmd)
+  elif os.environ.get(MAGIC_VAR, '0') == '0':
+    cgroups.Cgroup.InitSystem()
+    os.environ[MAGIC_VAR] = '1'
+    os.execvp('unshare', ['unshare', '-m', '--'] + argv)
+  else:
+    os.environ.pop(MAGIC_VAR)
 
 
 def main(argv):
@@ -285,10 +292,9 @@
   if cros_build_lib.IsInsideChroot():
     parser.error("This needs to be ran outside the chroot")
 
-  _ReExecuteAsRootIfNeeded([sys.argv[0]] + argv)
+  _ReExecuteIfNeeded([sys.argv[0]] + argv)
 
   host = os.uname()[4]
-
   if host != 'x86_64':
     parser.error(
         "cros_sdk is currently only supported on x86_64; you're running"