/// <summary> /// Checks that /// - a sideband file for a given process exists /// - the sideband file is not corrupt (its checksum checks out) /// - the process metadata recorded in the sideband file matches the metadata expected for this process /// </summary> private bool ValidateSidebandFileForProcess(Process process) { var sidebandFile = GetSidebandFile(process); if (!FileUtilities.FileExistsNoFollow(sidebandFile)) { return(failed(SidebandIntegrityCheckFailReason.FileNotFound)); } using (var reader = new SidebandReader(sidebandFile)) { if (!reader.ReadHeader(ignoreChecksum: false)) { return(failed(SidebandIntegrityCheckFailReason.ChecksumMismatch)); } var metadata = reader.ReadMetadata(); var expected = PipExecutor.CreateSidebandMetadata(Scheduler, process); if (!metadata.Equals(expected)) { return(failed(SidebandIntegrityCheckFailReason.MetadataMismatch, $"Expected: {expected}. Actual: {metadata}")); } return(true); } bool failed(SidebandIntegrityCheckFailReason reason, string details = "") { Logger.Log.SidebandIntegrityCheckForProcessFailed(LoggingContext, process.FormattedSemiStableHash, sidebandFile, reason.ToString(), details); return(false); } }
private void InvalidateSidebandFile(string sidebandFile, SidebandIntegrityCheckFailReason kind) { XAssert.FileExists(sidebandFile, "Sideband file for pipA not found."); switch (kind) { case SidebandIntegrityCheckFailReason.FileNotFound: AssertDeleteFile(sidebandFile, "Could not delete sideband file for pipA."); break; case SidebandIntegrityCheckFailReason.ChecksumMismatch: File.WriteAllText(path: sidebandFile, contents: "bogus sideband file"); break; case SidebandIntegrityCheckFailReason.MetadataMismatch: SidebandMetadata alteredMetadata; // read the header and the metadata from the original using (var reader = new SidebandReader(sidebandFile)) { XAssert.IsTrue(reader.ReadHeader(ignoreChecksum: false)); var originalMetadata = reader.ReadMetadata(); alteredMetadata = new SidebandMetadata(originalMetadata.PipSemiStableHash + 1, originalMetadata.StaticPipFingerprint); } // overwrite the original with a different metadata file where PiPSemiStableHash is different than in the original using (var writer = new SidebandWriter(alteredMetadata, sidebandFile, null)) { writer.EnsureHeaderWritten(); } break; default: XAssert.Fail($"Unknown kind: {kind}"); break; } }
/// <summary> /// Reads in parallel all writes recorded in given sideband files (<paramref name="sidebandFiles"/>). /// The task of reading paths from a single sideband file is delegated to <see cref="SidebandReader.ReadSidebandFile"/>. /// Exceptions of type <see cref="IOException"/> and <see cref="BuildXLException"/> are caught, logged, and ignored. /// </summary> internal string[] TryReadAllRecordedWrites(IReadOnlyList <string> sidebandFiles) { try { return(sidebandFiles .AsParallel(Context) .SelectMany(tryReadSidebandFile) .ToArray()); } catch (OperationCanceledException) { // No specific handling needed for cancellations. Build session will terminate return(CollectionUtilities.EmptyArray <string>()); } IEnumerable <string> tryReadSidebandFile(string filename) { try { return(SidebandReader.ReadSidebandFile(filename, ignoreChecksum: true)); } catch (Exception e) when(e is BuildXLException || e is IOException || e is OperationCanceledException) { Processes.Tracing.Logger.Log.CannotReadSidebandFileWarning(LoggingContext, filename, e.Message); return(CollectionUtilities.EmptyArray <string>()); } } }
/// <summary> /// Checks that /// - a sideband file for a given process exists /// - the sideband file is not corrupt (its checksum checks out) /// - the process metadata recorded in the sideband file matches the metadata expected for this process /// Returns true on success and the sideband state in the out parameter /// </summary> private bool TryGetAndValidateSidebandStateForProcess(Process process, out IReadOnlyCollection <AbsolutePath> paths) { var sidebandFile = GetSidebandFile(process); paths = null; if (!FileUtilities.FileExistsNoFollow(sidebandFile)) { return(failed(SidebandIntegrityCheckFailReason.FileNotFound)); } using (var reader = new SidebandReader(sidebandFile)) { if (!reader.ReadHeader(ignoreChecksum: false)) { return(failed(SidebandIntegrityCheckFailReason.ChecksumMismatch)); } var metadata = reader.ReadMetadata(); var expected = PipExecutor.CreateSidebandMetadata(Scheduler, process); if (!metadata.Equals(expected)) { return(failed(SidebandIntegrityCheckFailReason.MetadataMismatch, $"Expected: {expected}. Actual: {metadata}")); } paths = reader.ReadRecordedPaths().Select(p => AbsolutePath.Create(Context.PathTable, p)).ToHashSet(); return(true); } bool failed(SidebandIntegrityCheckFailReason reason, string details = "") { Logger.Log.SidebandIntegrityCheckForProcessFailed(LoggingContext, process.FormattedSemiStableHash, sidebandFile, reason.ToString(), details); return(false); } }
private bool TryReadSidebandFile(string filename, out SidebandMetadata metadata, out IEnumerable <string> paths) { try { // We ignore the checksum because even when the sideband file is compromised, // it is possible to call <see cref="ReadRecordedPaths"/> which will then try to recover // as many recorded paths as possible. (paths, metadata) = SidebandReader.ReadSidebandFile(filename, ignoreChecksum: true); return(true); } catch (Exception e) when(e is BuildXLException || e is IOException || e is OperationCanceledException) { Processes.Tracing.Logger.Log.CannotReadSidebandFileWarning(LoggingContext, filename, e.Message); metadata = null; paths = null; return(false); } }