Beispiel #1
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;
            }
Beispiel #3
0
        /// <nodoc />
        public SandboxConnectionLinuxDetours(Sandbox.ManagedFailureCallback failureCallback = null, bool isInTestMode = false)
        {
            IsInTestMode      = isInTestMode;
            m_failureCallback = failureCallback;

#if DEBUG
            BuildXL.Native.Processes.ProcessUtilities.SetNativeConfiguration(true);
#else
            BuildXL.Native.Processes.ProcessUtilities.SetNativeConfiguration(false);
#endif
        }
            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;
            }
        /// <summary>
        /// Initializes the sandbox kernel extension connection manager, setting up the kernel extension connection and workers that drain the
        /// kernel event queue and report file accesses
        /// </summary>
        public KextConnection(Config config = null, bool skipDisposingForTests = false)
        {
            m_reportQueueLastEnqueueTime = 0;
            m_kextConnectionInfo         = new Sandbox.KextConnectionInfo()
            {
                Error = Sandbox.KextSuccess
            };
            m_sharedMemoryInfo = new Sandbox.KextSharedMemoryInfo()
            {
                Error = Sandbox.KextSuccess
            };

            MeasureCpuTimes = config.MeasureCpuTimes;
            IsInTestMode    = skipDisposingForTests;

            // initialize kext connection
            Sandbox.InitializeKextConnection(ref m_kextConnectionInfo);
            if (m_kextConnectionInfo.Error != Sandbox.KextSuccess)
            {
                throw new BuildXLException($@"Unable to connect to sandbox kernel extension (Code: {m_kextConnectionInfo.Error}) - make sure it is loaded and retry! {KextInstallHelper}");
            }

            // check and set if the sandbox is running in debug configuration
            bool isDebug = false;

            Sandbox.CheckForDebugMode(ref isDebug, m_kextConnectionInfo);
            ProcessUtilities.SetNativeConfiguration(isDebug);

#if DEBUG
            if (!ProcessUtilities.IsNativeInDebugConfiguration())
#else
            if (ProcessUtilities.IsNativeInDebugConfiguration())
#endif
            {
                throw new BuildXLException($"Sandbox kernel extension build flavor missmatch - the extension must match the engine build flavor, Debug != Release. {KextInstallHelper}");
            }

            // check if the sandbox version matches
            var stringBufferLength = MaxVersionNumberLength + 1;
            var version            = new StringBuilder(stringBufferLength);
            Sandbox.KextVersionString(version, stringBufferLength);

            if (!RequiredKextVersionNumber.Equals(version.ToString().TrimEnd('\0')))
            {
                throw new BuildXLException($"Sandbox kernel extension version mismatch, the loaded kernel extension version '{version}' does not match the required version '{RequiredKextVersionNumber}'. {KextInstallHelper}");
            }

            if (config?.KextConfig != null)
            {
                if (!Sandbox.Configure(config.KextConfig.Value, m_kextConnectionInfo))
                {
                    throw new BuildXLException($"Unable to configure sandbox kernel extension");
                }
            }

            m_failureCallback = config?.FailureCallback;

            // Initialize the shared memory region
            Sandbox.InitializeKextSharedMemory(m_kextConnectionInfo, ref m_sharedMemoryInfo);
            if (m_sharedMemoryInfo.Error != Sandbox.KextSuccess)
            {
                throw new BuildXLException($"Unable to allocate shared memory region for worker (Code:{m_sharedMemoryInfo.Error})");
            }

            if (!SetFailureNotificationHandler())
            {
                throw new BuildXLException($"Unable to set sandbox kernel extension failure notification callback handler");
            }

            m_workerThread = new Thread(() => StartReceivingAccessReports(m_sharedMemoryInfo.Address, m_sharedMemoryInfo.Port));
            m_workerThread.IsBackground = true;
            m_workerThread.Priority     = ThreadPriority.Highest;
            m_workerThread.Start();

            unsafe bool SetFailureNotificationHandler()
            {
                return(Sandbox.SetFailureNotificationHandler(KextFailureCallback, m_kextConnectionInfo));

                void KextFailureCallback(void *refCon, int status)
                {
                    m_failureCallback?.Invoke(status, $"Unrecoverable kernel extension failure happened - try reloading the kernel extension or restart your system. {KextInstallHelper}");
                }
            }
        }