Esempio n. 1
0
        // Initialize the bottle, if necessary, then run a command in it.
        public static int ExecHandler(bool verbose, IEnumerable <string> command)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            // If already inside, just execute it.
            if (state.startedWithin)
            {
                return(Helpers.RunAndWait(command.First(), command.Skip(1).ToArray()));
            }

            using (var r = new RootPrivilege())
            {
                if (!state.existedAtStart)
                {
                    InitializeBottle(verbose);
                }

                // At this point, we should be inside an existing bottle, one way or another.

                RunCommand(verbose, command.ToArray());
            }

            return(0);
        }
Esempio n. 2
0
        // Initialize the bottle, if necessary, then start a login prompt in it.
        public static int LoginHandler(bool verbose)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            if (state.startedWithin)
            {
                Console.WriteLine("genie: already inside the bottle; cannot start login prompt!");
                return(EINVAL);
            }

            using (var r = new RootPrivilege())
            {
                if (!state.existedAtStart)
                {
                    InitializeBottle(verbose);
                }

                // At this point, we should be outside an existing bottle, one way or another.

                // It shouldn't matter whether we have setuid here, since we start the shell with
                // a login prompt, which reassigns uid appropriately.
                StartLogin(verbose);
            }

            return(0);
        }
Esempio n. 3
0
        // Initialize the bottle (if necessary) only
        public static int InitializeHandler(bool verbose)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            // If a bottle exists, we have succeeded already. Exit and report success.
            if (state.existedAtStart)
            {
                if (verbose)
                {
                    Console.WriteLine("genie: bottle already exists (no need to initialize).");
                }

                return(0);
            }

            // Daemonize expects real uid root as well as effective uid root.
            using (var r = new RootPrivilege())
            {
                // Init the bottle.
                InitializeBottle(verbose);
            }

            return(0);
        }
Esempio n. 4
0
        // Shut down the bottle and clean up.
        public static int ShutdownHandler(bool verbose)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            if (!state.existedAtStart)
            {
                Console.WriteLine("genie: no bottle exists.");
                return(EINVAL);
            }

            if (state.startedWithin)
            {
                Console.WriteLine("genie: cannot shut down bottle from inside bottle; exiting.");
                return(EINVAL);
            }

            using (var r = new RootPrivilege())
            {
                if (verbose)
                {
                    Console.WriteLine("genie: running systemctl poweroff within bottle");
                }

                var systemdPid = Helpers.GetSystemdPid();
                var sd         = Process.GetProcessById(systemdPid);

                Helpers.Chain("nsenter",
                              new string[] { "-t", systemdPid.ToString(), "-m", "-p", "systemctl", "poweroff" },
                              "running command failed; nsenter");

                Console.Write("Waiting for systemd exit...");

                // Wait for systemd to exit.
                int timeout = Config.SystemdStartupTimeout;

                while (!sd.WaitForExit(1000))
                {
                    Console.Write(".");
                    timeout--;

                    if (timeout < 0)
                    {
                        Console.WriteLine("\n\nTimed out waiting for systemd to exit.\nThis may indicate a systemd configuration error.\nAttempting to continue.");
                        break;
                    }
                }

                Console.WriteLine();

                if (Config.UpdateHostname)
                {
                    Thread.Sleep(500);
                    Helpers.DropHostname(verbose);
                }
            }

            return(0);
        }
Esempio n. 5
0
        // Shut down the bottle and clean up.
        public static int ShutdownHandler(bool verbose)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            if (!state.existedAtStart)
            {
                Console.WriteLine("genie: no bottle exists.");
                return(EINVAL);
            }

            if (state.startedWithin)
            {
                Console.WriteLine("genie: cannot shut down bottle from inside bottle; exiting.");
                return(EINVAL);
            }

            using (var r = new RootPrivilege())
            {
                if (verbose)
                {
                    Console.WriteLine("genie: running systemctl poweroff within bottle");
                }

                var systemdPid = Helpers.GetSystemdPid();
                var sd         = Process.GetProcessById(systemdPid);

                Helpers.Chain("nsenter",
                              new string[] { "-t", systemdPid.ToString(), "-m", "-p", "systemctl", "poweroff" },
                              "running command failed; nsenter");

                if (verbose)
                {
                    Console.WriteLine("genie: waiting for systemd to exit");
                }

                // Wait for systemd to exit (maximum 16 s).
                sd.WaitForExit(16000);

                if (Config.UpdateHostname)
                {
                    Thread.Sleep(500);
                    Helpers.DropHostname(verbose);
                }
            }

            return(0);
        }
Esempio n. 6
0
        // Shut down the bottle and clean up.
        public static int ShutdownHandler(bool verbose)
        {
            // Get the bottle state.
            var state = GetBottleState(verbose);

            if (!state.existedAtStart)
            {
                Console.WriteLine("genie: no bottle exists.");
                return(EINVAL);
            }

            if (state.startedWithin)
            {
                Console.WriteLine("genie: cannot shut down bottle from inside bottle; exiting.");
                return(EINVAL);
            }

            using (var r = new RootPrivilege())
            {
                if (verbose)
                {
                    Console.WriteLine("genie: running systemctl poweroff within bottle");
                }

                var systemdPid = Helpers.GetSystemdPid();
                var sd         = Process.GetProcessById(systemdPid);

                Helpers.Chain("nsenter",
                              new string[] { "-t", systemdPid.ToString(), "-m", "-p", "systemctl", "poweroff" },
                              "running command failed; nsenter");

                Console.Write("Waiting for systemd exit...");

                // Wait for systemd to exit.
                int timeout = Config.SystemdStartupTimeout;

                while (!sd.WaitForExit(1000))
                {
                    Console.Write(".");
                    timeout--;

                    if (timeout < 0)
                    {
                        Console.WriteLine("\n\nTimed out waiting for systemd to exit.\nThis may indicate a systemd configuration error.\nAttempting to continue.");
                        break;
                    }
                }

                Console.WriteLine();

                // Having unmounted the binfmts fs before starting systemd, we remount it now as
                // a courtesy. But remember, genie is not guaranteed to be idempotent, so don't
                // rely on this, for the love of Thompson and Ritchie!
                if (!Directory.Exists("/proc/sys/fs/binfmt_misc"))
                {
                    if (verbose)
                    {
                        Console.WriteLine("genie: remounting binfmt_misc filesystem as a courtesy");
                    }

                    if (!MountHelpers.Mount("binfmt_misc", "/proc/sys/fs/binfmt_misc", FsType.BinaryFormats))
                    {
                        Console.WriteLine("genie: failed to remount binfmt_misc filesystem; attempting to continue");
                    }
                }

                if (Config.ResolvedStub)
                {
                    Helpers.RemoveResolvSymlink(verbose);
                }

                if (Config.UpdateHostname)
                {
                    Thread.Sleep(500);
                    Helpers.DropHostname(verbose);
                }
            }

            return(0);
        }