private void NotifyKextPipTerminated(long pipId, IEnumerable <ReportedProcess> survivingChildProcesses) { // TODO: bundle this into a single message var distinctProcessIds = new HashSet <uint>(survivingChildProcesses.Select(p => p.ProcessId)); foreach (var processId in distinctProcessIds) { KextConnection.NotifyKextPipProcessTerminated(pipId, (int)processId); } }
private async Task StartAsync() { base.CreateAndSetUpProcess(); Process.StartInfo.FileName = "/bin/sh"; Process.StartInfo.Arguments = string.Empty; Process.StartInfo.RedirectStandardInput = true; Process.Start(); Process.BeginOutputReadLine(); Process.BeginErrorReadLine(); // Generate "Process Created" report because the rest of the system expects to see it before any other file access reports // // IMPORTANT: do this before notifying sandbox kernel extension, because otherwise it can happen that a report // from the extension is received before the "process created" report is handled, causing // a "Should see a process creation before its accesses" assertion exception. ReportProcessCreated(); // Allow read access for /bin/sh ProcessInfo.FileAccessManifest.AddPath( AbsolutePath.Create(PathTable, Process.StartInfo.FileName), mask: FileAccessPolicy.MaskNothing, values: FileAccessPolicy.AllowReadAlways); if (MeasureCpuTime) { // Allow read access for /usr/bin/time ProcessInfo.FileAccessManifest.AddPath( AbsolutePath.Create(PathTable, TimeUtil), mask: FileAccessPolicy.MaskNothing, values: FileAccessPolicy.AllowReadAlways); } if (!KextConnection.NotifyKextPipStarted(ProcessInfo.FileAccessManifest, this)) { ThrowCouldNotStartProcess("Failed to notify kernel extension about process start, make sure the extension is loaded"); } try { await FeedStdInAsync(); SetProcessStartedExecuting(); m_processTreeTimeoutTask = ProcessTreeTimeoutTask(); } catch (IOException e) { // IOException can happen if the process is forcefully killed while we're feeding its std in. // When that happens, instead of crashing, just make sure the process is killed. LogProcessState($"IOException caught while feeding the standard input: {e.Message}"); await KillAsync(); } }
/// <summary> /// Waits for all child processes to finish within a timeout limit and then termiantes all still running children after that point. /// After all the children have been taken care of, the method waits for pending report processing to finish, then returns the /// collected reports. /// </summary> internal override async Task <SandboxedProcessReports> GetReportsAsync() { if (!Killed) { var awaitedTask = await Task.WhenAny(m_pendingReports.Completion, m_processTreeTimeoutTask); if (awaitedTask == m_processTreeTimeoutTask) { LogProcessState("Waiting for reports timed out; any surviving processes will be forcefully killed."); await KillAsync(); } } // in any case must wait for pending reports to complete, because we must not freeze m_reports before that happens await m_pendingReports.Completion; // at this point this pip is done executing (it's only left to construct SandboxedProcessResult, // which is done by the base class) so notify the sandbox kernel extension connection manager about it. KextConnection.NotifyKextProcessFinished(PipId, this); return(IgnoreReportedAccesses ? null : m_reports); }