/// <nodoc /> public SandboxedProcessMacKext(SandboxedProcessInfo info, bool ignoreReportedAccesses = false, bool?overrideMeasureTime = null) : base(info) { Contract.Requires(info.FileAccessManifest != null); Contract.Requires(info.SandboxedKextConnection != null); IgnoreReportedAccesses = ignoreReportedAccesses; MeasureCpuTime = overrideMeasureTime.HasValue ? overrideMeasureTime.Value : info.SandboxedKextConnection.MeasureCpuTimes; m_reports = new SandboxedProcessReports( info.FileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener); m_pendingReports = new ActionBlock <AccessReport>( HandleKextReport, new ExecutionDataflowBlockOptions { #if FEATURE_CORECLR EnsureOrdered = true, #endif BoundedCapacity = DataflowBlockOptions.Unbounded, MaxDegreeOfParallelism = 1, // Must be one, otherwise SandboxedPipExecutor will fail asserting valid reports }); }
public void Dispose() { using (m_queryJobDataLock.AcquireWriteLock()) { // Prevent further data queries m_disposeStarted = true; } if (m_processStarted) { InternalKill(); m_resultTaskCompletionSource.Task.Wait(); } m_detouredProcess?.Dispose(); m_detouredProcess = null; m_output?.Dispose(); m_output = null; m_error?.Dispose(); m_error = null; m_reports = null; m_fileAccessManifestStreamWrapper.Dispose(); }
/// <nodoc /> public SandboxedProcessMacKext(SandboxedProcessInfo info, bool ignoreReportedAccesses = false, bool?overrideMeasureTime = null) : base(info) { Contract.Requires(info.FileAccessManifest != null); Contract.Requires(info.SandboxedKextConnection != null); IgnoreReportedAccesses = ignoreReportedAccesses; MeasureCpuTime = overrideMeasureTime.HasValue ? overrideMeasureTime.Value : info.SandboxedKextConnection.MeasureCpuTimes; m_reports = new SandboxedProcessReports( info.FileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener); m_pendingReports = new ActionBlock <AccessReport>( HandleKextReport, new ExecutionDataflowBlockOptions { EnsureOrdered = true, BoundedCapacity = DataflowBlockOptions.Unbounded, MaxDegreeOfParallelism = 1, // Must be one, otherwise SandboxedPipExecutor will fail asserting valid reports }); // install a 'ProcessStarted' handler that informs the kext of the newly started process ProcessStarted += () => OnProcessStartedAsync().GetAwaiter().GetResult(); }
/// <nodoc /> public SandboxedProcessMacKext(SandboxedProcessInfo info) : base(info) { Contract.Requires(info.FileAccessManifest != null); Contract.Requires(info.SandboxedKextConnection != null); m_processInfo = info; m_reports = new SandboxedProcessReports( info.FileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener); m_pendingReports = new ActionBlock <Sandbox.AccessReport>( (Action <Sandbox.AccessReport>)HandleKextReport, new ExecutionDataflowBlockOptions { #if FEATURE_CORECLR EnsureOrdered = true, #endif BoundedCapacity = ExecutionDataflowBlockOptions.Unbounded, MaxDegreeOfParallelism = 1, // Must be one, otherwise SandboxedPipExecutor will fail asserting valid reports }); }
/// <nodoc /> public SandboxedProcessUnix(SandboxedProcessInfo info, bool ignoreReportedAccesses = false, bool?overrideMeasureTime = null) : base(info) { Contract.Requires(info.FileAccessManifest != null); Contract.Requires(info.SandboxConnection != null); PipId = info.FileAccessManifest.PipId; SandboxConnection = info.SandboxConnection; ChildProcessTimeout = info.NestedProcessTerminationTimeout; AllowedSurvivingChildProcessNames = info.AllowedSurvivingChildProcessNames; ReportQueueProcessTimeoutForTests = info.ReportQueueProcessTimeoutForTests; IgnoreReportedAccesses = ignoreReportedAccesses; RootJailInfo = info.RootJailInfo; MeasureCpuTime = overrideMeasureTime.HasValue ? overrideMeasureTime.Value : info.SandboxConnection.MeasureCpuTimes; m_perfAggregator = new PerfAggregator(); m_perfCollector = new CancellableTimedAction( callback: UpdatePerfCounters, intervalMs: (int)PerfProbeInternal.TotalMilliseconds); m_reports = new SandboxedProcessReports( info.FileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener, info.SidebandWriter, info.FileSystemView); var useSingleProducer = !(SandboxConnection.Kind == SandboxKind.MacOsHybrid || SandboxConnection.Kind == SandboxKind.MacOsDetours); var executionOptions = new ExecutionDataflowBlockOptions { EnsureOrdered = true, SingleProducerConstrained = useSingleProducer, BoundedCapacity = DataflowBlockOptions.Unbounded, MaxDegreeOfParallelism = 1 // Must be one, otherwise SandboxedPipExecutor will fail asserting valid reports }; m_pendingReports = new ActionBlock <AccessReport>(HandleAccessReport, executionOptions); // install a 'ProcessStarted' handler that informs the sandbox of the newly started process ProcessStarted += (pid) => OnProcessStartedAsync(info).GetAwaiter().GetResult(); }
/// <inheritdoc /> public async Task <SandboxedProcessResult> GetResultAsync() { Contract.Requires(Started); SandboxedProcessReports reports = null; await m_processExecutor.WaitForExitAsync(); if (m_processExecutor.Killed) { // call here this.KillAsync() because a subclass may override it // to do some extra processing when a process is killed await KillAsync(); } LogProcessState("Waiting for reports to be received"); reports = await GetReportsAsync(); m_reportsReceivedTime = DateTime.UtcNow; reports?.Freeze(); await m_processExecutor.WaitForStdOutAndStdErrAsync(); var reportFileAccesses = ProcessInfo.FileAccessManifest?.ReportFileAccesses == true; var fileAccesses = reportFileAccesses ? (reports?.FileAccesses ?? s_emptyFileAccessesSet) : null; return(new SandboxedProcessResult { ExitCode = m_processExecutor.TimedOut ? ExitCodes.Timeout : Process.ExitCode, Killed = Killed, TimedOut = m_processExecutor.TimedOut, HasDetoursInjectionFailures = HasSandboxFailures, JobAccountingInformation = GetJobAccountingInfo(), StandardOutput = m_output.Freeze(), StandardError = m_error.Freeze(), HasReadWriteToReadFileAccessRequest = reports?.HasReadWriteToReadFileAccessRequest ?? false, AllUnexpectedFileAccesses = reports?.FileUnexpectedAccesses ?? s_emptyFileAccessesSet, FileAccesses = fileAccesses, DetouringStatuses = reports?.ProcessDetoursStatuses, ExplicitlyReportedFileAccesses = reports?.ExplicitlyReportedFileAccesses, Processes = CoalesceProcesses(reports?.Processes), MessageProcessingFailure = reports?.MessageProcessingFailure, DumpCreationException = m_dumpCreationException, DumpFileDirectory = ProcessInfo.TimeoutDumpDirectory, PrimaryProcessTimes = GetProcessTimes(), SurvivingChildProcesses = CoalesceProcesses(GetSurvivingChildProcesses()) }); }
public void Dispose() { if (m_processStarted) { InternalKill(); m_resultTaskCompletionSource.Task.Wait(); } m_detouredProcess?.Dispose(); m_detouredProcess = null; m_output?.Dispose(); m_output = null; m_error?.Dispose(); m_error = null; m_reports = null; m_fileAccessManifestStreamWrapper.Dispose(); }
/// <nodoc /> public SandboxedProcessMac(SandboxedProcessInfo info, bool ignoreReportedAccesses = false, bool?overrideMeasureTime = null) : base(info) { Contract.Requires(info.FileAccessManifest != null); Contract.Requires(info.SandboxConnection != null); IgnoreReportedAccesses = ignoreReportedAccesses; MeasureCpuTime = overrideMeasureTime.HasValue ? overrideMeasureTime.Value : info.SandboxConnection.MeasureCpuTimes; m_perfAggregator = new PerfAggregator(); m_perfCollector = new CancellableTimedAction( callback: UpdatePerfCounters, intervalMs: (int)PerfProbeInternal.TotalMilliseconds); m_reports = new SandboxedProcessReports( info.FileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener, info.SharedOpaqueOutputLogger); m_pendingReports = new ActionBlock <AccessReport>( HandleAccessReport, new ExecutionDataflowBlockOptions { EnsureOrdered = true, BoundedCapacity = DataflowBlockOptions.Unbounded, MaxDegreeOfParallelism = 1, // Must be one, otherwise SandboxedPipExecutor will fail asserting valid reports }); // install a 'ProcessStarted' handler that informs the sandbox of the newly started process ProcessStarted += () => OnProcessStartedAsync().GetAwaiter().GetResult(); }
internal SandboxedProcess(SandboxedProcessInfo info) { Contract.Requires(info != null); Contract.Requires(!info.Timeout.HasValue || info.Timeout.Value <= Process.MaxTimeout); // there could be a race here, but it just doesn't matter if (s_binaryPaths == null) { s_binaryPaths = new BinaryPaths(); // this can take a while; performs I/O } // If unspecified make the injection timeout the DefaultProcessTimeoutInMinutes. Also, make it no less than DefaultProcessTimeoutInMinutes. m_timeoutMins = info.Timeout.HasValue ? ((uint)info.Timeout.Value.TotalMinutes) : SandboxConfiguration.DefaultProcessTimeoutInMinutes; if (m_timeoutMins < SandboxConfiguration.DefaultProcessTimeoutInMinutes) { m_timeoutMins = SandboxConfiguration.DefaultProcessTimeoutInMinutes; } m_fileAccessManifest = info.FileAccessManifest; m_fileAccessManifestStreamWrapper = Pools.MemoryStreamPool.GetInstance(); m_bufferSize = SandboxedProcessInfo.BufferSize; m_allowedSurvivingChildProcessNames = info.AllowedSurvivingChildProcessNames; m_nestedProcessTerminationTimeout = info.NestedProcessTerminationTimeout; m_loggingContext = info.LoggingContext; Encoding inputEncoding = info.StandardInputEncoding ?? Console.InputEncoding; m_standardInputReader = info.StandardInputReader; m_pathTable = info.PathTable; Encoding outputEncoding = info.StandardOutputEncoding ?? Console.OutputEncoding; m_output = new SandboxedProcessOutputBuilder( outputEncoding, info.MaxLengthInMemory, info.FileStorage, SandboxedProcessFile.StandardOutput, info.StandardOutputObserver); Encoding errorEncoding = info.StandardErrorEncoding ?? Console.OutputEncoding; m_error = new SandboxedProcessOutputBuilder( errorEncoding, info.MaxLengthInMemory, info.FileStorage, SandboxedProcessFile.StandardError, info.StandardErrorObserver); m_reports = m_fileAccessManifest != null ? new SandboxedProcessReports( m_fileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener, info.SidebandWriter) : null; Contract.Assume(inputEncoding != null); Contract.Assert(errorEncoding != null); Contract.Assert(outputEncoding != null); m_detouredProcess = new DetouredProcess( SandboxedProcessInfo.BufferSize, info.GetCommandLine(), info.WorkingDirectory, info.GetUnicodeEnvironmentBlock(), inputEncoding, errorEncoding, m_error.AppendLine, outputEncoding, m_output.AppendLine, OnProcessExitingAsync, OnProcessExited, info.Timeout, info.DisableConHostSharing, info.LoggingContext, info.TimeoutDumpDirectory, info.ContainerConfiguration, // If there is any process configured to breakway from the sandbox, then we need to allow // this to happen at the job object level setJobBreakawayOk: m_fileAccessManifest.ProcessesCanBreakaway, info.CreateJobObjectForCurrentProcess); }
internal SandboxedProcess(SandboxedProcessInfo info) { Contract.Requires(info != null); Contract.Requires(!info.Timeout.HasValue || info.Timeout.Value <= Process.MaxTimeout); // there could be a race here, but it just doesn't matter if (s_binaryPaths == null) { s_binaryPaths = new BinaryPaths(); // this can take a while; performs I/O } // If unspecified make the injection timeout 10 mins. Also, make it no less than 10 mins. m_timeoutMins = info.Timeout.HasValue ? ((uint)info.Timeout.Value.TotalMinutes) : 10; if (m_timeoutMins < 10) { m_timeoutMins = 10; } m_fileAccessManifest = info.FileAccessManifest; m_fileAccessManifestStreamWrapper = Pools.MemoryStreamPool.GetInstance(); m_bufferSize = SandboxedProcessInfo.BufferSize; m_nestedProcessTerminationTimeout = info.NestedProcessTerminationTimeout; Encoding inputEncoding = info.StandardInputEncoding ?? Console.InputEncoding; m_standardInputReader = info.StandardInputReader; m_pathTable = info.PathTable; Encoding outputEncoding = info.StandardOutputEncoding ?? Console.OutputEncoding; m_output = new SandboxedProcessOutputBuilder( outputEncoding, info.MaxLengthInMemory, info.FileStorage, SandboxedProcessFile.StandardOutput, info.StandardOutputObserver); Encoding errorEncoding = info.StandardErrorEncoding ?? Console.OutputEncoding; m_error = new SandboxedProcessOutputBuilder( errorEncoding, info.MaxLengthInMemory, info.FileStorage, SandboxedProcessFile.StandardError, info.StandardErrorObserver); m_reports = m_fileAccessManifest != null ? new SandboxedProcessReports( m_fileAccessManifest, info.PathTable, info.PipSemiStableHash, info.PipDescription, info.LoggingContext, info.DetoursEventListener) : null; Contract.Assume(inputEncoding != null); Contract.Assert(errorEncoding != null); Contract.Assert(outputEncoding != null); m_processIdListener = info.ProcessIdListener; m_detouredProcess = new DetouredProcess( SandboxedProcessInfo.BufferSize, info.GetCommandLine(), info.WorkingDirectory, info.GetUnicodeEnvironmentBlock(), inputEncoding, errorEncoding, m_error.AppendLine, outputEncoding, m_output.AppendLine, OnProcessExitingAsync, OnProcessExited, info.Timeout, info.DisableConHostSharing, info.LoggingContext, info.TimeoutDumpDirectory); }