示例#1
0
        /// <summary>
        /// Runs a target process inside the sandbox asynchronously
        /// </summary>
        /// <param name="instance">A SandboxExecRunner instance</param>
        /// <param name="exec">The programs full command line including its arguments</param>
        /// <param name="workingDirectory">Working directory in which to start the process</param>
        /// <returns>Task that will execute the process and its arguments inside the BuildXL Sandbox</returns>
        public static Task <ISandboxedProcess> ExecuteAsync(SandboxExecRunner instance, string[] exec, string workingDirectory)
        {
            var processFileName = exec[0];
            var processInfo     = CreateSandboxedProcessInfo(processFileName, instance);

            processInfo.Timeout              = TimeSpan.FromSeconds(instance.m_options.ProcessTimeout);
            processInfo.Arguments            = ExtractAndEscapeCommandLineArguments(exec);
            processInfo.WorkingDirectory     = workingDirectory;
            processInfo.EnvironmentVariables = BuildParameters.GetFactory(null).PopulateFromEnvironment();
            instance.m_pathTable             = processInfo.PathTable;

            return(SandboxedProcessFactory.StartAsync(processInfo, forceSandboxing: true));
        }
示例#2
0
        /// <summary>
        /// Creates a SandboxedProcessInfo object that can be used to run a target program within the BuildXL Sandbox and
        /// forces the Sandbox to explicitly report all file accesses observed
        /// </summary>
        /// <param name="processFileName">The fully qualifying file name of the process to run inside the sandbox</param>
        /// <param name="instance">A SandboxExecRunner instance</param>
        /// <returns>SandboxedProcessInfo object that is configured to explicitly report all observed file accesses</returns>
        public static SandboxedProcessInfo CreateSandboxedProcessInfo(string processFileName, SandboxExecRunner instance)
        {
            var sandboxProcessInfo = new SandboxedProcessInfo(
                new PathTable(),
                fileStorage: instance,
                fileName: processFileName,
                disableConHostSharing: true,
                sandboxConnection: instance.m_sandboxConnection,
                loggingContext: s_loggingContext);

            sandboxProcessInfo.PipDescription = processFileName;

            sandboxProcessInfo.StandardOutputEncoding = Encoding.UTF8;
            sandboxProcessInfo.StandardOutputObserver = PrintToStdout;

            sandboxProcessInfo.StandardErrorEncoding = Encoding.UTF8;
            sandboxProcessInfo.StandardErrorObserver = PrintToStderr;

            // track directory creation
            sandboxProcessInfo.FileAccessManifest.EnforceAccessPoliciesOnDirectoryCreation = instance.m_options.TrackDirectoryCreation;

            // Enable explicit file access reporting
            sandboxProcessInfo.FileAccessManifest.ReportFileAccesses         = true;
            sandboxProcessInfo.FileAccessManifest.FailUnexpectedFileAccesses = false;
            sandboxProcessInfo.FileAccessManifest.PipId = Interlocked.Increment(ref s_pipIdCounter);
            return(sandboxProcessInfo);
        }
示例#3
0
        private static int RunTool(Options options, string[] procArgs)
        {
            if (procArgs.Length < 1)
            {
                var macOSUsageDescription = OperatingSystemHelper.IsUnixOS ? $" [/{ArgReportQueueSizeMB}:<1-1024>] [/{ArgEnableReportBatching}[+,-]]" : "";
                PrintToStderr($"Usage: SandboxExec [[/{ArgVerbose}[+,-]] [/{ArgLogToStdOut}[+,-]] [/{ArgProcessTimeout}:seconds] [/{ArgTrackDirectoryCreation}] [/{ArgEnableStatistics}[+,-]] [/{ArgUseEndpointSecuritySandbox}[+,-]]{macOSUsageDescription} --] executable [arg1 arg2 ...]");
                return(1);
            }

            if (!Path.IsPathRooted(procArgs[0]))
            {
                PrintToStderr("The path to the executable must be specified as an absolute path. Exiting.");
                return(1);
            }

            Telemetry.TelemetryStartup(options.EnableTelemetry);
            CleanupOutputs();

            var instance = new SandboxExecRunner(options);

            SandboxedProcessResult result;
            Stopwatch sandboxingTime;
            var       overallTime = Stopwatch.StartNew();

            using (var process = ExecuteAsync(instance, procArgs, workingDirectory: Directory.GetCurrentDirectory()).GetAwaiter().GetResult())
            {
                sandboxingTime = Stopwatch.StartNew();
                result         = process.GetResultAsync().GetAwaiter().GetResult();
                sandboxingTime.Stop();

                PrintToStdout($"Process {procArgs[0]}:{process.ProcessId} exited with exit code: {result.ExitCode}");
            }

            var dedupeTime = Stopwatch.StartNew();

            var accessReportCount = result.FileAccesses.Count;

            // Dedupe reported file accesses
            var distinctAccessReports = instance.DedupeAccessReports(
                result.FileAccesses,
                result.ExplicitlyReportedFileAccesses,
                result.AllUnexpectedFileAccesses);

            dedupeTime.Stop();

            var outputTime = Stopwatch.StartNew();

            if (options.LogToStdOut)
            {
                foreach (var report in distinctAccessReports)
                {
                    PrintToStdout(report);
                }
            }
            else
            {
                var path = Path.Combine(Directory.GetCurrentDirectory(), AccessOutput);
                try
                {
                    File.WriteAllLines(path, distinctAccessReports);
                }
                catch (IOException ex)
                {
                    PrintToStderr($"Could not write file access report file to {path}. Got excecption instead: " + ex.ToString());
                }
            }
            outputTime.Stop();

            var disposeTime = Stopwatch.StartNew();

            if (instance.m_sandboxConnection != null)
            {
                // Take care of releasing sandbox kernel extension resources on macOS
                instance.m_sandboxConnection.Dispose();
            }
            disposeTime.Stop();

            overallTime.Stop();

            if (options.EnableTelemetry)
            {
                PrintToStdout("\nTime unit is: ms\n");
                PrintToStdout($"Overall execution time:                       {overallTime.ElapsedMilliseconds}");
                PrintToStdout($"Time spent executing process with sandboxing: {sandboxingTime.ElapsedMilliseconds}");
                PrintToStdout($"Time spent deduping access reports:           {dedupeTime.ElapsedMilliseconds}");
                PrintToStdout($"Time spent outputting access reports:         {outputTime.ElapsedMilliseconds}");
                PrintToStdout($"Time spent disposing kernel connection:       {disposeTime.ElapsedMilliseconds}");
                PrintToStdout($"Number of access reports before deduping:     {accessReportCount}");
                PrintToStdout($"Number of access reports after deduping:      {distinctAccessReports.Count}");

                PrintToStdout("");
                PrintToStdout("Statistics ::");
                foreach (KeyValuePair <string, long> kvp in SandboxedProcessFactory.Counters.AsStatistics())
                {
                    PrintToStdout($"{kvp.Key} = {kvp.Value}");
                }
                PrintToStdout("");
            }

            CollectAndUploadCrashReports(options.EnableTelemetry);
            Telemetry.TelemetryShutdown();

            return(result.ExitCode);
        }