Beispiel #1
0
        /// <nodoc />
        public SandboxExecRunner(Options options)
        {
            m_options           = options;
            s_crashCollector    = OperatingSystemHelper.IsUnixOS ? new CrashCollectorMacOS(new[] { CrashType.SandboxExec, CrashType.Kernel }) : null;
            m_sandboxConnection = OperatingSystemHelper.IsUnixOS
                ?
#if PLATFORM_OSX
                                  m_options.UseEndpointSecuritySandbox
                    ? (ISandboxConnection) new SandboxConnectionES()
                    :
#endif
                                  (ISandboxConnection) new SandboxConnectionKext(
                new SandboxConnectionKext.Config
            {
                FailureCallback = (int status, string description) =>
                {
                    m_sandboxConnection.Dispose();
                    throw new SystemException($"Received unrecoverable error from the sandbox (Code: {status.ToString("X")}, Description: {description}), please reload the extension and retry.");
                },
                KextConfig = new Sandbox.KextConfig
                {
                    ReportQueueSizeMB    = m_options.ReportQueueSizeMB,
                    EnableReportBatching = m_options.EnableReportBatching,
#if PLATFORM_OSX
                    EnableCatalinaDataPartitionFiltering = OperatingSystemHelper.IsMacOSCatalinaOrHigher
#endif
                },
            })
                : null;
        }
Beispiel #2
0
        /// <summary>
        /// Creates instance
        /// </summary>
        public SandboxedProcessInfo(
            PathTable pathTable,
            ISandboxedProcessFileStorage fileStorage,
            string fileName,
            FileAccessManifest fileAccessManifest,
            bool disableConHostSharing,
            ContainerConfiguration containerConfiguration,
            bool testRetries = false,
            LoggingContext loggingContext = null,
            IDetoursEventListener detoursEventListener = null,
            ISandboxConnection sandboxConnection       = null)
        {
            Contract.Requires(pathTable != null);
            Contract.Requires(fileStorage != null);
            Contract.Requires(fileName != null);

            PathTable             = pathTable;
            FileAccessManifest    = fileAccessManifest;
            FileStorage           = fileStorage;
            FileName              = fileName;
            DisableConHostSharing = disableConHostSharing;

            // This should be set for testing purposes only.
            TestRetries = testRetries;

            NestedProcessTerminationTimeout = DefaultNestedProcessTerminationTimeout;
            LoggingContext         = loggingContext;
            DetoursEventListener   = detoursEventListener;
            SandboxConnection      = sandboxConnection;
            ContainerConfiguration = containerConfiguration;
        }
Beispiel #3
0
 /// <summary>
 /// Creates instance for test
 /// </summary>
 public SandboxedProcessInfo(
     PathTable pathTable,
     ISandboxedProcessFileStorage fileStorage,
     string fileName,
     bool disableConHostSharing,
     bool testRetries = false,
     LoggingContext loggingContext = null,
     IDetoursEventListener detoursEventListener    = null,
     ISandboxConnection sandboxConnection          = null,
     ContainerConfiguration containerConfiguration = null,
     FileAccessManifest fileAccessManifest         = null)
     : this(
         pathTable,
         fileStorage,
         fileName,
         fileAccessManifest ?? new FileAccessManifest(pathTable),
         disableConHostSharing,
         containerConfiguration ?? ContainerConfiguration.DisabledIsolation,
         testRetries,
         loggingContext,
         detoursEventListener,
         sandboxConnection)
 {
     Contract.Requires(pathTable != null);
     Contract.Requires(fileStorage != null);
     Contract.Requires(fileName != null);
 }
Beispiel #4
0
 /// <summary>
 /// Creates instance for test
 /// </summary>
 public SandboxedProcessInfo(
     PathTable pathTable,
     [CanBeNull] ISandboxedProcessFileStorage fileStorage,
     string fileName,
     bool disableConHostSharing,
     LoggingContext loggingContext,
     bool testRetries = false,
     IDetoursEventListener detoursEventListener    = null,
     ISandboxConnection sandboxConnection          = null,
     ContainerConfiguration containerConfiguration = null,
     FileAccessManifest fileAccessManifest         = null,
     bool createJobObjectForCurrentProcess         = true)
     : this(
         pathTable,
         fileStorage,
         fileName,
         fileAccessManifest ?? new FileAccessManifest(pathTable),
         disableConHostSharing,
         containerConfiguration ?? ContainerConfiguration.DisabledIsolation,
         loggingContext,
         testRetries,
         detoursEventListener,
         sandboxConnection,
         createJobObjectForCurrentProcess : createJobObjectForCurrentProcess)
 {
     Contract.RequiresNotNull(pathTable);
     Contract.RequiresNotNull(fileName);
 }
        /// <summary>
        /// Creates instance
        /// </summary>
        public SandboxedProcessInfo(
            PathTable pathTable,
            [CanBeNull] ISandboxedProcessFileStorage fileStorage,
            string fileName,
            FileAccessManifest fileAccessManifest,
            bool disableConHostSharing,
            ContainerConfiguration containerConfiguration,
            LoggingContext loggingContext,
            bool testRetries = false,
            IDetoursEventListener detoursEventListener = null,
            ISandboxConnection sandboxConnection       = null,
            SidebandWriter sidebandWriter         = null,
            bool createJobObjectForCurrentProcess = true)
        {
            Contract.RequiresNotNull(pathTable);
            Contract.RequiresNotNull(fileName);

            PathTable             = pathTable;
            FileAccessManifest    = fileAccessManifest;
            FileStorage           = fileStorage;
            FileName              = fileName;
            DisableConHostSharing = disableConHostSharing;

            // This should be set for testing purposes only.
            TestRetries = testRetries;

            NestedProcessTerminationTimeout = DefaultNestedProcessTerminationTimeout;
            LoggingContext                   = loggingContext;
            DetoursEventListener             = detoursEventListener;
            SandboxConnection                = sandboxConnection;
            ContainerConfiguration           = containerConfiguration;
            SidebandWriter                   = sidebandWriter;
            CreateJobObjectForCurrentProcess = createJobObjectForCurrentProcess;
        }
Beispiel #6
0
        /// <remarks>
        /// Sets <see cref="FileAccessManifest.FailUnexpectedFileAccesses"/> to false if not explicitly set
        /// </remarks>
        protected SandboxedProcessInfo ToProcessInfo(
            Process process,
            string pipDescription = null,
            FileAccessManifest fileAccessManifest       = null,
            IDetoursEventListener detoursListener       = null,
            bool disableConHostSharing                  = false,
            Dictionary <string, string> overrideEnvVars = null,
            ISandboxConnection sandboxConnection        = null)
        {
            var envVars = Override(
                BuildParameters.GetFactory().PopulateFromEnvironment().ToDictionary(),
                overrideEnvVars);

            var methodName = DiscoverCurrentlyExecutingXunitTestMethodFQN();

            pipDescription = pipDescription != null
                ? methodName + " - " + pipDescription
                : methodName;

            var info = new SandboxedProcessInfo(
                Context.PathTable,
                this,
                process.Executable.Path.ToString(Context.PathTable),
                detoursEventListener: detoursListener,
                sandboxConnection: sandboxConnection ?? GetSandboxConnection(),
                disableConHostSharing: disableConHostSharing,
                fileAccessManifest: fileAccessManifest,
                loggingContext: LoggingContext)
            {
                PipSemiStableHash    = 0x1234,
                PipDescription       = pipDescription,
                WorkingDirectory     = TemporaryDirectory,
                Arguments            = process.Arguments.ToString(Context.PathTable),
                Timeout              = TimeSpan.FromMinutes(15),
                EnvironmentVariables = BuildParameters.GetFactory().PopulateFromDictionary(envVars)
            };

            if (fileAccessManifest == null)
            {
                info.FileAccessManifest.FailUnexpectedFileAccesses = false;
            }

            foreach (var path in process.UntrackedPaths)
            {
                info.FileAccessManifest.AddPath(path, values: FileAccessPolicy.AllowAll, mask: FileAccessPolicy.MaskNothing);
            }

            foreach (var dir in process.UntrackedScopes)
            {
                info.FileAccessManifest.AddScope(dir, FileAccessPolicy.MaskNothing, FileAccessPolicy.AllowAll);
            }

            info.FileAccessManifest.PipId = GetNextPipId();

            return(info);
        }
Beispiel #7
0
 /// <summary>
 /// Creates instance
 /// </summary>
 public SandboxedProcessInfo(
     ISandboxedProcessFileStorage fileStorage,
     string fileName,
     bool disableConHostSharing,
     bool testRetries = false,
     LoggingContext loggingContext = null,
     IDetoursEventListener detoursEventListener = null,
     ISandboxConnection sandboxConnection       = null)
     : this(new PathTable(), fileStorage, fileName, disableConHostSharing, testRetries, loggingContext, detoursEventListener, sandboxConnection)
 {
 }
Beispiel #8
0
            public PipQueueTestExecutionEnvironment(BuildXLContext context, IConfiguration configuration, PipTable pipTable, string tempDirectory, ISandboxConnection SandboxConnection = null)
            {
                Contract.Requires(context != null);
                Contract.Requires(configuration != null);

                Context              = context;
                LoggingContext       = CreateLoggingContextForTest();
                Configuration        = configuration;
                FileContentTable     = FileContentTable.CreateNew();
                ContentFingerprinter = new PipContentFingerprinter(
                    context.PathTable,
                    artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                    ExtraFingerprintSalts.Default(),
                    pathExpander: PathExpander);
                PipTable            = pipTable;
                PipFragmentRenderer = this.CreatePipFragmentRenderer();
                IpcProvider         = IpcFactory.GetProvider();
                var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

                Cache = InMemoryCacheFactory.Create();
                LocalDiskContentStore = new LocalDiskContentStore(LoggingContext, context.PathTable, FileContentTable, tracker);

                m_sandboxConnectionKext  = SandboxConnection;
                m_expectedWrittenContent = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_wellKnownFiles         = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_producers      = new ConcurrentDictionary <FileArtifact, Pip>();
                m_filesystemView = new TestPipGraphFilesystemView(Context.PathTable);
                var fileSystemView = new FileSystemView(Context.PathTable, m_filesystemView, LocalDiskContentStore);

                TempCleaner = new TestMoveDeleteCleaner(tempDirectory);

                State = new PipExecutionState(
                    configuration,
                    cache: new PipTwoPhaseCache(LoggingContext, Cache, context, PathExpander),
                    unsafeConfiguration: configuration.Sandbox.UnsafeSandboxConfiguration,
                    preserveOutputsSalt: ContentHashingUtilities.CreateRandom(),
                    fileAccessWhitelist: FileAccessWhitelist,
                    directoryMembershipFingerprinter: this,
                    pathExpander: PathExpander,
                    executionLog: null,
                    fileSystemView: fileSystemView,
                    fileContentManager: new FileContentManager(this, new NullOperationTracker()),
                    directoryMembershipFinterprinterRuleSet: null);

                m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

                ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
            }
Beispiel #9
0
        /// <nodoc />
        public SandboxExecRunner(Options options)
        {
            m_options        = options;
            s_crashCollector = OperatingSystemHelper.IsMacOS
                ? new CrashCollectorMacOS(new[] { CrashType.SandboxExec, CrashType.Kernel })
                : null;

            if (!OperatingSystemHelper.IsMacOSCatalinaOrHigher &&
                (m_options.SandboxKindUsed == SandboxKind.MacOsEndpointSecurity || m_options.SandboxKindUsed == SandboxKind.MacOsHybrid))
            {
                throw new NotSupportedException("EndpointSecurity and Hybrid sandbox types can't be run on system older than macOS Catalina (10.15+).");
            }

            // m_sandboxConnection
            if (OperatingSystemHelper.IsLinuxOS)
            {
                m_sandboxConnection = new SandboxConnectionLinuxDetours(FailureCallback);
            }
            else if (OperatingSystemHelper.IsMacOS)
            {
                if (m_options.SandboxKindUsed == SandboxKind.MacOsKext)
                {
                    m_sandboxConnection = new SandboxConnectionKext(new SandboxConnectionKext.Config
                    {
                        FailureCallback = FailureCallback,
                        KextConfig      = new Sandbox.KextConfig
                        {
                            ReportQueueSizeMB    = m_options.ReportQueueSizeMB,
                            EnableReportBatching = m_options.EnableReportBatching,
#if PLATFORM_OSX
                            EnableCatalinaDataPartitionFiltering = OperatingSystemHelper.IsMacOSCatalinaOrHigher
#endif
                        }
                    });
                }
                else
                {
                    m_sandboxConnection = new SandboxConnection(m_options.SandboxKindUsed, isInTestMode: false, measureCpuTimes: true);
                }
            }
            else
            {
                m_sandboxConnection = null;
            }
        }
Beispiel #10
0
 /// <remarks>
 /// This constructor is never used in this project, but there exist external projects that
 /// compile against this assembly and already depend on this constructor.
 /// </remarks>
 public SandboxedProcessInfo(
     [CanBeNull] ISandboxedProcessFileStorage fileStorage,
     string fileName,
     bool disableConHostSharing,
     bool testRetries = false,
     LoggingContext loggingContext = null,
     IDetoursEventListener detoursEventListener = null,
     ISandboxConnection sandboxConnection       = null,
     bool createJobObjectForCurrentProcess      = true)
     : this(
         new PathTable(),
         fileStorage,
         fileName,
         disableConHostSharing,
         loggingContext ?? new LoggingContext("ExternalComponent"),
         testRetries,
         detoursEventListener,
         sandboxConnection,
         createJobObjectForCurrentProcess : createJobObjectForCurrentProcess)
 {
 }
Beispiel #11
0
        private void SetSandboxConnectionIfNeeded(SandboxedProcessInfo info)
        {
            if (OperatingSystemHelper.IsLinuxOS)
            {
                m_sandboxConnection = new SandboxConnectionLinuxDetours(SandboxConnectionFailureCallback);
            }
            else if (OperatingSystemHelper.IsMacOS)
            {
                m_sandboxConnection = new SandboxConnectionKext(
                    new SandboxConnectionKext.Config
                {
                    FailureCallback = SandboxConnectionFailureCallback,
                    KextConfig      = new Interop.Unix.Sandbox.KextConfig
                    {
                        ReportQueueSizeMB = ReportQueueSizeForKextMB,
#if PLATFORM_OSX
                        EnableCatalinaDataPartitionFiltering = OperatingSystemHelper.IsMacWithoutKernelExtensionSupport
#endif
                    }
                });
            }

            info.SandboxConnection = m_sandboxConnection;
        }
Beispiel #12
0
 /// <summary>
 /// For unit tests only.
 /// </summary>
 public SandboxExecRunner(ISandboxConnection connection)
 {
     m_options           = Options.Defaults;
     m_sandboxConnection = connection;
 }
Beispiel #13
0
        protected override bool InitSandboxConnectionKext(LoggingContext loggingContext, ISandboxConnection SandboxConnectionKext = null)
        {
            if (SandboxingWithKextEnabled)
            {
                SandboxConnection = SandboxConnectionKext ?? XunitBuildXLTest.GetSandboxConnection();
            }

            return(false);
        }
Beispiel #14
0
        /// <summary>
        /// Creates an execution environment for a single pip. To run pips incrementally, the <paramref name="fileContentTable"/> and <paramref name="pipCache"/> should be specified.
        /// </summary>
        public DummyPipExecutionEnvironment(
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration config,
            FileContentTable fileContentTable = null,
            EngineCache pipCache = null,
            SemanticPathExpander semanticPathExpander           = null,
            PipContentFingerprinter.PipDataLookup pipDataLookup = null,
            FileAccessWhitelist fileAccessWhitelist             = null,
            bool allowUnspecifiedSealedDirectories = false,
            PipTable pipTable                    = null,
            IIpcProvider ipcProvider             = null,
            ISandboxConnection sandboxConnection = null)
        {
            Contract.Requires(context != null);
            Contract.Requires(config != null);

            LoggingContext = loggingContext;
            Context        = context;

            // Ensure paths visible when debugging
            PathTable.DebugPathTable = Context.PathTable;
            Configuration            = config;
            PipTable             = pipTable;
            PathExpander         = semanticPathExpander ?? SemanticPathExpander.Default;
            ContentFingerprinter = new PipContentFingerprinter(
                Context.PathTable,
                artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                new ExtraFingerprintSalts(config, PipFingerprintingVersion.TwoPhaseV2, fingerprintSalt: null, searchPathToolsHash: null),
                pathExpander: PathExpander,
                pipDataLookup: pipDataLookup);
            PipFragmentRenderer = this.CreatePipFragmentRenderer();
            IpcProvider         = ipcProvider ?? IpcFactory.GetProvider();

            FileContentTable    = fileContentTable ?? FileContentTable.CreateNew();
            Cache               = pipCache;
            FileAccessWhitelist = fileAccessWhitelist;
            m_allowUnspecifiedSealedDirectories = allowUnspecifiedSealedDirectories;
            m_sandboxConnectionKext             = sandboxConnection;

            if (Cache == null)
            {
                Cache = InMemoryCacheFactory.Create();
            }

            var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

            LocalDiskContentStore = new LocalDiskContentStore(loggingContext, context.PathTable, FileContentTable, tracker);
            PipGraphView          = new TestPipGraphFilesystemView(Context.PathTable);
            m_operationTracker    = new OperationTracker(loggingContext);

            var fileSystemView = new FileSystemView(Context.PathTable, PipGraphView, LocalDiskContentStore);

            var preserveOutputsSalt = UnsafeOptions.PreserveOutputsNotUsed;

            if (config.Sandbox.UnsafeSandboxConfiguration.PreserveOutputs != PreserveOutputsMode.Disabled)
            {
                preserveOutputsSalt = ContentHashingUtilities.HashString(Guid.NewGuid().ToString());
            }

            State = new PipExecutionState(
                config,
                cache: new PipTwoPhaseCache(loggingContext, Cache, context, PathExpander),
                fileAccessWhitelist: FileAccessWhitelist,
                directoryMembershipFingerprinter: this,
                pathExpander: PathExpander,
                executionLog: ExecutionLogRecorder,
                fileSystemView: fileSystemView,
                fileContentManager: GetFileContentManager(),
                directoryMembershipFinterprinterRuleSet: null,
                unsafeConfiguration: config.Sandbox.UnsafeSandboxConfiguration,
                preserveOutputsSalt: preserveOutputsSalt,
                serviceManager: new DummyServiceManager());

            m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

            ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
        }