예제 #1
0
 /// <inheritdoc />
 public void NotifyRootProcessExited(long pipId, SandboxedProcessUnix process)
 {
     if (m_pipProcesses.TryGetValue(pipId, out var info))
     {
         info.RemovePid(process.ProcessId);
     }
 }
예제 #2
0
            internal Info(Sandbox.ManagedFailureCallback failureCallback, SandboxedProcessUnix process, string reportsFifoPath, string famPath, string debugLogPath)
            {
                m_failureCallback = failureCallback;
                Process           = process;
                ReportsFifoPath   = reportsFifoPath;
                FamPath           = famPath;
                DebugLogJailPath  = debugLogPath;

                m_pathCache       = new Dictionary <string, PathCacheRecord>();
                m_activeProcesses = new ConcurrentDictionary <int, byte>
                {
                    [process.ProcessId] = 1
                };
                m_activeProcessesChecker = new CancellableTimedAction(
                    CheckActiveProcesses,
                    intervalMs: Math.Min((int)process.ChildProcessTimeout.TotalMilliseconds, (int)ActiveProcessesCheckerInterval.TotalMilliseconds));

                // create a write handle (used to keep the fifo open, i.e.,
                // the 'read' syscall won't receive EOF until we close this writer
                m_lazyWriteHandle = new Lazy <SafeFileHandle>(() =>
                {
                    LogDebug($"Opening FIFO '{ReportsFifoPath}' for writing");
                    return(IO.Open(ReportsFifoPath, IO.OpenFlags.O_WRONLY, 0));
                });

                // start a background thread for reading from the FIFO
                m_workerThread = new Thread(StartReceivingAccessReports);
                m_workerThread.IsBackground = true;
                m_workerThread.Priority     = ThreadPriority.Highest;
            }
            internal Info(Sandbox.ManagedFailureCallback failureCallback, SandboxedProcessUnix process, string reportsFifoPath, string famPath)
            {
                m_failureCallback = failureCallback;
                Process           = process;
                ReportsFifoPath   = reportsFifoPath;
                FamPath           = famPath;

                m_pathCache       = new Dictionary <string, PathCacheRecord>();
                m_activeProcesses = new HashSet <int>
                {
                    process.ProcessId
                };

                // create a write handle (used to keep the fifo open, i.e.,
                // the 'read' syscall won't receive EOF until we close this writer
                m_lazyWriteHandle = new Lazy <SafeFileHandle>(() =>
                {
                    LogDebug($"Opening FIFO '{ReportsFifoPath}' for writing");
                    return(IO.Open(ReportsFifoPath, IO.OpenFlags.O_WRONLY, 0));
                });

                // start a background thread for reading from the FIFO
                m_workerThread = new Thread(StartReceivingAccessReports);
                m_workerThread.IsBackground = true;
                m_workerThread.Priority     = ThreadPriority.Highest;
            }
예제 #4
0
 /// <inheritdoc />
 public bool NotifyPipFinished(long pipId, SandboxedProcessUnix process)
 {
     if (m_pipProcesses.TryRemove(pipId, out var info))
     {
         info.Dispose();
         return(true);
     }
     else
     {
         return(false);
     }
 }
예제 #5
0
 /// <inheritdoc />
 public bool NotifyPipFinished(long pipId, SandboxedProcessUnix process)
 {
     if (m_pipProcesses.TryRemove(pipId, out var proc))
     {
         Contract.Assert(process == proc);
         return(true);
     }
     else
     {
         return(false);
     }
 }
            internal Info(Sandbox.ManagedFailureCallback failureCallback, SandboxedProcessUnix process, string reportsFifoPath, string famPath, string debugLogPath, bool isInTestMode)
            {
                m_isInTestMode       = isInTestMode;
                m_stopRequestCounter = 0;
                m_completeAccessReportProcessingCounter = 0;
                m_failureCallback = failureCallback;
                Process           = process;
                ReportsFifoPath   = reportsFifoPath;
                FamPath           = famPath;
                DebugLogJailPath  = debugLogPath;

                m_waitToCompleteCts = new CancellationTokenSource();
                m_pathCache         = new Dictionary <string, PathCacheRecord>();
                m_activeProcesses   = new ConcurrentDictionary <int, byte>
                {
                    [process.ProcessId] = 1
                };
                m_activeProcessesChecker = new CancellableTimedAction(
                    CheckActiveProcesses,
                    intervalMs: Math.Min((int)process.ChildProcessTimeout.TotalMilliseconds, (int)ActiveProcessesCheckerInterval.TotalMilliseconds));

                // create a write handle (used to keep the fifo open, i.e.,
                // the 'read' syscall won't receive EOF until we close this writer
                m_lazyWriteHandle = new Lazy <SafeFileHandle>(() =>
                {
                    LogDebug($"Opening FIFO '{ReportsFifoPath}' for writing");
                    return(IO.Open(ReportsFifoPath, IO.OpenFlags.O_WRONLY, 0));
                });

                // action block where parsing and processing of received ActionReport bytes is done
                m_accessReportProcessingBlock = new ActionBlock <(PooledObjectWrapper <byte[]> wrapper, int length)>(ProcessBytes, new ExecutionDataflowBlockOptions
                {
                    BoundedCapacity        = DataflowBlockOptions.Unbounded,
                    MaxDegreeOfParallelism = 1,
                    EnsureOrdered          = true
                });

                // start a background thread for reading from the FIFO
                m_workerThread = new Thread(StartReceivingAccessReports);
                m_workerThread.IsBackground = true;
                m_workerThread.Priority     = ThreadPriority.Highest;
            }
예제 #7
0
        /// <inheritdoc />
        public bool NotifyPipStarted(LoggingContext loggingContext, FileAccessManifest fam, SandboxedProcessUnix process)
        {
            Contract.Requires(process.Started);
            Contract.Requires(process.PipId != 0);

            string rootDir      = process.RootJail ?? Path.GetTempPath();
            string fifoPath     = Path.Combine(rootDir, $"bxl_Pip{process.PipSemiStableHash:X}.{process.ProcessId}.fifo");
            string famPath      = Path.ChangeExtension(fifoPath, ".fam");
            string debugLogPath = null;

            if (IsInTestMode)
            {
                debugLogPath = process.ToPathInsideRootJail(Path.ChangeExtension(fifoPath, ".log"));
                fam.AddPath(toAbsPath(debugLogPath), mask: FileAccessPolicy.MaskAll, values: FileAccessPolicy.AllowAll);
            }

            // serialize FAM
            using (var wrapper = Pools.MemoryStreamPool.GetInstance())
            {
                var debugFlags = true;
                ArraySegment <byte> manifestBytes = fam.GetPayloadBytes(
                    loggingContext,
                    new FileAccessSetup {
                    DllNameX64 = string.Empty, DllNameX86 = string.Empty, ReportPath = process.ToPathInsideRootJail(fifoPath)
                },
                    wrapper.Instance,
                    timeoutMins: 10, // don't care
                    debugFlagsMatch: ref debugFlags);

                Contract.Assert(manifestBytes.Offset == 0);
                File.WriteAllBytes(famPath, manifestBytes.ToArray());
            }

            process.LogDebug($"Saved FAM to '{famPath}'");

            // create a FIFO (named pipe)
            if (IO.MkFifo(fifoPath, IO.FilePermissions.S_IRWXU) != 0)
            {
                m_failureCallback?.Invoke(1, $"Creating FIFO {fifoPath} failed");
                return(false);
            }

            process.LogDebug($"Created FIFO at '{fifoPath}'");

            // create and save info for this pip
            var info = new Info(m_failureCallback, process, fifoPath, famPath, debugLogPath);

            if (!m_pipProcesses.TryAdd(process.PipId, info))
            {
                throw new BuildXLException($"Process with PidId {process.PipId} already exists");
            }

            info.Start();
            return(true);

            AbsolutePath toAbsPath(string path) => AbsolutePath.Create(process.PathTable, path);
        }
예제 #8
0
 /// <inheritdoc />
 public void NotifyRootProcessExited(long pipId, SandboxedProcessUnix process)
 {
     // this implementation keeps track of what the root process is an when it exits,
     // so it doesn't need to be notified about it separately
 }
예제 #9
0
        /// <inheritdoc />
        public bool NotifyPipStarted(LoggingContext loggingContext, FileAccessManifest fam, SandboxedProcessUnix process)
        {
            Contract.Requires(process.Started);
            Contract.Requires(fam.PipId != 0);

            if (!m_pipProcesses.TryAdd(fam.PipId, process))
            {
                throw new BuildXLException($"Process with PidId {fam.PipId} already exists");
            }

            var setup = new FileAccessSetup()
            {
                DllNameX64 = string.Empty,
                DllNameX86 = string.Empty,
                ReportPath = process.ExecutableAbsolutePath, // piggybacking on ReportPath to pass full executable path
            };

            using (var wrapper = Pools.MemoryStreamPool.GetInstance())
            {
                var debugFlags = true;
                ArraySegment <byte> manifestBytes = fam.GetPayloadBytes(
                    loggingContext,
                    setup,
                    wrapper.Instance,
                    timeoutMins: 10, // don't care because on Mac we don't kill the process from the Kext once it times out
                    debugFlagsMatch: ref debugFlags);

                Contract.Assert(manifestBytes.Offset == 0);

                var result = Sandbox.SendPipStarted(
                    processId: process.ProcessId,
                    pipId: fam.PipId,
                    famBytes: manifestBytes.Array,
                    famBytesLength: manifestBytes.Count,
                    type: Sandbox.ConnectionType.Kext,
                    info: ref m_kextConnectionInfo);

                return(result);
            }
        }