Example #1
0
        public void NativeWin32ExceptionIncludesSystemFormattedString()
        {
            const int ErrorAccessDenied = 5;

            var ex = new NativeWin32Exception(ErrorAccessDenied, "Prefix");

            XAssert.IsTrue(ex.Message.Contains("Access is denied"));
            XAssert.IsTrue(ex.Message.Contains("Prefix"));
            XAssert.AreEqual(ErrorAccessDenied, ex.NativeErrorCode);
        }
Example #2
0
        /// <summary>
        /// Describes the operation that cause this reported file access, including all parameter value, except the path
        /// </summary>
        public string Describe()
        {
            using (PooledObjectWrapper <StringBuilder> wrapper = Pools.GetStringBuilder())
            {
                StringBuilder sb = wrapper.Instance;
                sb.Append('[');
                sb.Append(Process.Path);
                sb.Append(':');
                sb.Append(Process.ProcessId);
                sb.Append(']');

                if (RequestedAccess != RequestedAccess.None)
                {
                    sb.AppendFormat("({0:G})", RequestedAccess);
                }

                sb.Append(' ');

                switch (Operation)
                {
                case ReportedFileOperation.ZwCreateFile:
                case ReportedFileOperation.ZwOpenFile:
                case ReportedFileOperation.NtCreateFile:
                case ReportedFileOperation.CreateFile:
                case ReportedFileOperation.Unknown:
                {
                    sb.Append(Operation.ToString());
                    sb.Append("(..., ");
                    UInt32FlagsFormatter <DesiredAccess> .Append(sb, (uint)DesiredAccess);

                    sb.Append(", ");
                    UInt32FlagsFormatter <ShareMode> .Append(sb, (uint)ShareMode);

                    sb.Append(", , ");
                    UInt32EnumFormatter <CreationDisposition> .Append(sb, (uint)CreationDisposition);

                    sb.Append(", ");
                    UInt32FlagsFormatter <FlagsAndAttributes> .Append(sb, (uint)FlagsAndAttributes);

                    sb.Append(")");
                    break;
                }

                case ReportedFileOperation.CopyFileSource:
                {
                    sb.Append("CopyFile([Source], ...)");
                    break;
                }

                case ReportedFileOperation.CopyFileDestination:
                {
                    sb.Append("CopyFile(..., [Destination])");
                    break;
                }

                case ReportedFileOperation.CreateHardLinkSource:
                {
                    sb.Append("CreateHardLink(..., [ExistingFile)");
                    break;
                }

                case ReportedFileOperation.CreateHardLinkDestination:
                {
                    sb.Append("CreateHardLink([NewLink], ...)");
                    break;
                }

                case ReportedFileOperation.MoveFileSource:
                {
                    sb.Append("MoveFile([Source], ...)");
                    break;
                }

                case ReportedFileOperation.MoveFileDestination:
                {
                    sb.Append("MoveFile(..., [Destination])");
                    break;
                }

                case ReportedFileOperation.SetFileInformationByHandleSource:
                {
                    sb.Append("SetFileInformationByHandle([Source], ...)");
                    break;
                }

                case ReportedFileOperation.SetFileInformationByHandleDest:
                {
                    sb.Append("SetFileInformationByHandle(..., [Destination])");
                    break;
                }

                case ReportedFileOperation.ZwSetRenameInformationFileSource:
                {
                    sb.Append("ZwSetRenameInformationFile([Source], ...)");
                    break;
                }

                case ReportedFileOperation.ZwSetRenameInformationFileDest:
                {
                    sb.Append("ZwSetRenameInformationFile(..., [Destination])");
                    break;
                }

                case ReportedFileOperation.ZwSetFileNameInformationFileSource:
                {
                    sb.Append("ZwSetFileNameInformationFile([Source], ...)");
                    break;
                }

                case ReportedFileOperation.ZwSetFileNameInformationFileDest:
                {
                    sb.Append("ZwSetFileNameInformationFile(..., [Destination])");
                    break;
                }

                case ReportedFileOperation.MoveFileWithProgressSource:
                {
                    sb.Append("MoveFileWithProgress([Source]...)");
                    break;
                }

                case ReportedFileOperation.MoveFileWithProgressDest:
                {
                    sb.Append("MoveFileWithProgress([Dest]...)");
                    break;
                }

                case ReportedFileOperation.FindFirstFileEx:
                {
                    sb.Append("FindFirstFileEx(...)");
                    if (RequestedAccess == RequestedAccess.Enumerate)
                    {
                        sb.Append(", ");
                        sb.Append("Enumerate Pattern:" + EnumeratePattern);
                    }

                    break;
                }

                default:
                {
                    sb.Append(Enum.GetName(typeof(ReportedFileOperation), Operation)).Append("(...)");
                    break;
                }
                }

                if (Error != 0)
                {
                    sb.AppendFormat(CultureInfo.InvariantCulture, " => (0x{0:X8}) ", Error);
                    sb.Append(NativeWin32Exception.GetFormattedMessageForNativeErrorCode(unchecked ((int)Error)));
                }

                if (Usn != NoUsn)
                {
                    sb.AppendFormat(CultureInfo.InvariantCulture, " (USN 0x{0:X8}) ", Usn);
                }

                // If the status was Denied, don't include it in the description,
                // because an access that was denied by manifest may have been
                // allowed in practice (no failure injection), and the message
                // would be confusing.
                if (Status != FileAccessStatus.Denied)
                {
                    // Other modes are interesting and should be logged
                    sb.Append(" => ");
                    sb.Append(Status);
                }

                return(sb.ToString());
            }
        }
        private static void ConfigureWciFilter(IntPtr hJob, IReadOnlyCollection <ExpandedAbsolutePath> sourcePaths, string destinationPath, List <string> wciRetries)
        {
            var layerDescriptors = new NativeContainerUtilities.WC_LAYER_DESCRIPTOR[sourcePaths.Count];

            int i = 0;

            foreach (ExpandedAbsolutePath sourcePath in sourcePaths)
            {
                var layerDescriptor = new NativeContainerUtilities.WC_LAYER_DESCRIPTOR
                {
                    // By default we always set the layer so it inherits the descriptor. This
                    // makes hardlinks (ACLed for deny-write) and exposed via copy-on-write writable
                    // The sparse flag is not set explicitly since we use the general sparse isolation mode
                    // which implies that each layer will be sparse
                    Flags   = NativeContainerUtilities.LayerDescriptorFlags.InheritSecurity,
                    LayerId = NativeContainerUtilities.ToGuid(Guid.NewGuid()),
                    Path    = sourcePath.ExpandedPath,
                };
                layerDescriptors[i] = layerDescriptor;
                i++;
            }

            var reparsePointData = new NativeContainerUtilities.WC_REPARSE_POINT_DATA
            {
                Flags      = 0,
                LayerId    = layerDescriptors[0].LayerId,
                NameLength = 0,
                Name       = string.Empty
            };

            var hresult = -1;

            hresult = NativeContainerUtilities.WciSetReparsePointData(
                destinationPath,
                ref reparsePointData,
                (UInt16)Marshal.OffsetOf(typeof(NativeContainerUtilities.WC_REPARSE_POINT_DATA), "Name"));

            if (hresult != 0)
            {
                throw new NativeWin32Exception(Marshal.GetLastWin32Error(), I($"Unable to setup the reparse point data for '{destinationPath}'."));
            }

            hresult = -1;
            // We try to setup the WCI filter on a retry loop to workaround an existing issue
            // in the driver behavior, where the setup sometimes fails.
            var retries = s_wciRetries;

            while (hresult != 0 && retries > 0)
            {
                // Isolation is set to hard because we want the virtualized source path to be
                // completely isolated (e.g. with 'hard' we will get copy-on-write behavior and
                // tombstones when any deletion happens inside the container).
                // It is also set as sparse so all layers recursively merge without needing an explicit reparse point
                // for each of them
                hresult = NativeContainerUtilities.WciSetupFilter(
                    hJob,
                    NativeContainerUtilities.WC_ISOLATION_MODE.IsolationModeSparseHard,
                    destinationPath,
                    layerDescriptors,
                    (uint)layerDescriptors.Length,
                    NativeContainerUtilities.WC_NESTING_MODE.WcNestingModeInner);

                retries--;
                if (hresult != 0)
                {
                    wciRetries.Add(I($"Error setting WCI filter for {hJob} from '{string.Join(Environment.NewLine, sourcePaths)}' to '{destinationPath}'. Retries left: {retries}. Details: {NativeWin32Exception.GetFormattedMessageForNativeErrorCode(hresult)}"));
                }
            }

            if (hresult != 0)
            {
                throw new NativeWin32Exception(Marshal.GetLastWin32Error(), I($"Unable to setup the WCI filter for source paths '{string.Join(Environment.NewLine, sourcePaths)}' to destination path '{destinationPath}'."));
            }
        }
        /// <summary><see cref="ProcessUtilities.TryCleanUpContainer"/></summary>
        public bool TryCleanUpContainer(IntPtr hJob, out IEnumerable <string> errors)
        {
            var cleanUpErrors = new List <string>();

            var result = NativeContainerUtilities.WcCleanupContainer(hJob, null);

            if (result != 0)
            {
                cleanUpErrors.Add(I($"Cannot clean up container for job object {hJob}. Details: {NativeWin32Exception.GetFormattedMessageForNativeErrorCode(result)}"));
            }

            errors = cleanUpErrors;
            return(cleanUpErrors.Count == 0);
        }
Example #5
0
 /// <inheritdoc />
 public override string Describe()
 {
     return(NativeWin32Exception.GetFormattedMessageForNativeErrorCode(NativeErrorCode, messagePrefix: Message));
 }
Example #6
0
 public static NativeFailure CreateFromException(NativeWin32Exception exception)
 {
     return(new NativeFailure(exception.NativeErrorCode, exception.Message));
 }