From bfc343e80131261e2f6d359ea9efa323fddfe372 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Fri, 11 Oct 2019 12:53:29 -0500 Subject: [PATCH] Add some validation to StorageBase --- src/LibHac/Fs/FileBase.cs | 2 +- src/LibHac/Fs/FileHandleStorage.cs | 14 ++-- src/LibHac/Fs/FileSystemClient.AccessLog.cs | 4 +- src/LibHac/Fs/ResultFs.cs | 2 +- src/LibHac/Fs/SaveData.cs | 4 +- src/LibHac/Fs/StorageBase.cs | 65 +++++++++++++++++-- src/LibHac/Fs/SubStorage2.cs | 26 ++++---- .../EmulatedGameCardStorageCreator.cs | 10 +-- src/LibHac/FsSystem/SubStorage.cs | 2 +- 9 files changed, 89 insertions(+), 40 deletions(-) diff --git a/src/LibHac/Fs/FileBase.cs b/src/LibHac/Fs/FileBase.cs index 244c8200..887dfa98 100644 --- a/src/LibHac/Fs/FileBase.cs +++ b/src/LibHac/Fs/FileBase.cs @@ -55,7 +55,7 @@ namespace LibHac.Fs public Result GetSize(out long size) { - size = 0; + size = default; if (IsDisposed) return ResultFs.PreconditionViolation.Log(); return GetSizeImpl(out size); diff --git a/src/LibHac/Fs/FileHandleStorage.cs b/src/LibHac/Fs/FileHandleStorage.cs index 729e2d78..83c379c9 100644 --- a/src/LibHac/Fs/FileHandleStorage.cs +++ b/src/LibHac/Fs/FileHandleStorage.cs @@ -21,7 +21,7 @@ namespace LibHac.Fs FsClient = Handle.File.Parent.FsClient; } - public override Result Read(long offset, Span destination) + public override Result ReadImpl(long offset, Span destination) { lock (_locker) { @@ -30,14 +30,13 @@ namespace LibHac.Fs Result rc = UpdateSize(); if (rc.IsFailure()) return rc; - if (destination.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log(); if (!IsRangeValid(offset, destination.Length, FileSize)) return ResultFs.ValueOutOfRange.Log(); return FsClient.ReadFile(Handle, offset, destination); } } - public override Result Write(long offset, ReadOnlySpan source) + public override Result WriteImpl(long offset, ReadOnlySpan source) { lock (_locker) { @@ -46,26 +45,25 @@ namespace LibHac.Fs Result rc = UpdateSize(); if (rc.IsFailure()) return rc; - if (source.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log(); if (!IsRangeValid(offset, source.Length, FileSize)) return ResultFs.ValueOutOfRange.Log(); return FsClient.WriteFile(Handle, offset, source); } } - public override Result Flush() + public override Result FlushImpl() { return FsClient.FlushFile(Handle); } - public override Result SetSize(long size) + public override Result SetSizeImpl(long size) { FileSize = InvalidSize; return FsClient.SetFileSize(Handle, size); } - public override Result GetSize(out long size) + public override Result GetSizeImpl(out long size) { size = default; @@ -87,7 +85,7 @@ namespace LibHac.Fs return Result.Success; } - public override void Dispose() + protected override void Dispose(bool disposing) { if (CloseHandle) { diff --git a/src/LibHac/Fs/FileSystemClient.AccessLog.cs b/src/LibHac/Fs/FileSystemClient.AccessLog.cs index e4f3bee8..f7e89383 100644 --- a/src/LibHac/Fs/FileSystemClient.AccessLog.cs +++ b/src/LibHac/Fs/FileSystemClient.AccessLog.cs @@ -205,8 +205,8 @@ namespace LibHac.Fs { None = 0, Application = 1 << 0, - Internal = 1 << 1, - All = Application | Internal + System = 1 << 1, + All = Application | System } [Flags] diff --git a/src/LibHac/Fs/ResultFs.cs b/src/LibHac/Fs/ResultFs.cs index 75a6a0ba..c4b1173f 100644 --- a/src/LibHac/Fs/ResultFs.cs +++ b/src/LibHac/Fs/ResultFs.cs @@ -135,7 +135,7 @@ public static Result RemapStorageMapFull => new Result(ModuleFs, 6811); - public static Result Result6902 => new Result(ModuleFs, 6902); + public static Result SubStorageNotInitialized => new Result(ModuleFs, 6902); public static Result MountNameNotFound => new Result(ModuleFs, 6905); } } diff --git a/src/LibHac/Fs/SaveData.cs b/src/LibHac/Fs/SaveData.cs index 5ae9468d..a0bc1b21 100644 --- a/src/LibHac/Fs/SaveData.cs +++ b/src/LibHac/Fs/SaveData.cs @@ -31,7 +31,7 @@ namespace LibHac.Fs public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId, ulong ownerId, long size, long journalSize, uint flags) { - return fs.RunOperationWithAccessLog(LocalAccessLogMode.Internal, + return fs.RunOperationWithAccessLog(LocalAccessLogMode.System, () => { IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); @@ -89,7 +89,7 @@ namespace LibHac.Fs public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId) { - return fs.RunOperationWithAccessLog(LocalAccessLogMode.Internal, + return fs.RunOperationWithAccessLog(LocalAccessLogMode.System, () => { IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); diff --git a/src/LibHac/Fs/StorageBase.cs b/src/LibHac/Fs/StorageBase.cs index 732b611f..60fe4f93 100644 --- a/src/LibHac/Fs/StorageBase.cs +++ b/src/LibHac/Fs/StorageBase.cs @@ -1,20 +1,71 @@ using System; +using System.Threading; namespace LibHac.Fs { public abstract class StorageBase : IStorage { - public abstract Result Read(long offset, Span destination); - public abstract Result Write(long offset, ReadOnlySpan source); - public abstract Result Flush(); - public abstract Result SetSize(long size); - public abstract Result GetSize(out long size); + // 0 = not disposed; 1 = disposed + private int _disposedState; + private bool IsDisposed => _disposedState != 0; - public virtual void Dispose() { } + public abstract Result ReadImpl(long offset, Span destination); + public abstract Result WriteImpl(long offset, ReadOnlySpan source); + public abstract Result FlushImpl(); + public abstract Result GetSizeImpl(out long size); + public abstract Result SetSizeImpl(long size); + + public Result Read(long offset, Span destination) + { + if (IsDisposed) return ResultFs.PreconditionViolation.Log(); + + return ReadImpl(offset, destination); + } + + public Result Write(long offset, ReadOnlySpan source) + { + if (IsDisposed) return ResultFs.PreconditionViolation.Log(); + + return WriteImpl(offset, source); + } + + public Result Flush() + { + if (IsDisposed) return ResultFs.PreconditionViolation.Log(); + + return FlushImpl(); + } + + public Result SetSize(long size) + { + if (IsDisposed) return ResultFs.PreconditionViolation.Log(); + + return SetSizeImpl(size); + } + + public Result GetSize(out long size) + { + size = default; + if (IsDisposed) return ResultFs.PreconditionViolation.Log(); + + return GetSizeImpl(out size); + } + + public void Dispose() + { + // Make sure Dispose is only called once + if (Interlocked.CompareExchange(ref _disposedState, 1, 0) == 0) + { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + protected virtual void Dispose(bool disposing) { } public static bool IsRangeValid(long offset, long size, long totalSize) { - return size <= totalSize && offset <= totalSize - size; + return offset >= 0 && size >= 0 && size <= totalSize && offset <= totalSize - size; } } } diff --git a/src/LibHac/Fs/SubStorage2.cs b/src/LibHac/Fs/SubStorage2.cs index e919a04e..0c9790f4 100644 --- a/src/LibHac/Fs/SubStorage2.cs +++ b/src/LibHac/Fs/SubStorage2.cs @@ -23,38 +23,38 @@ namespace LibHac.Fs Size = size; } - public override Result Read(long offset, Span destination) + public override Result ReadImpl(long offset, Span destination) { - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); if (destination.Length == 0) return Result.Success; - if (Size < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log(); + if (!IsRangeValid(offset, destination.Length, Size)) return ResultFs.ValueOutOfRange.Log(); return BaseStorage.Read(Offset + offset, destination); } - public override Result Write(long offset, ReadOnlySpan source) + public override Result WriteImpl(long offset, ReadOnlySpan source) { - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); if (source.Length == 0) return Result.Success; - if (Size < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log(); + if (!IsRangeValid(offset, source.Length, Size)) return ResultFs.ValueOutOfRange.Log(); return BaseStorage.Write(Offset + offset, source); } - public override Result Flush() + public override Result FlushImpl() { - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); return BaseStorage.Flush(); } - public override Result SetSize(long size) + public override Result SetSizeImpl(long size) { - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); if (!IsResizable) return ResultFs.SubStorageNotResizable.Log(); - if (size < 0 || Offset < 0) return ResultFs.ValueOutOfRange.Log(); + if (size < 0 || Offset < 0) return ResultFs.InvalidSize.Log(); Result rc = BaseStorage.GetSize(out long baseSize); if (rc.IsFailure()) return rc; @@ -72,11 +72,11 @@ namespace LibHac.Fs return Result.Success; } - public override Result GetSize(out long size) + public override Result GetSizeImpl(out long size) { size = default; - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); size = Size; return Result.Success; diff --git a/src/LibHac/FsService/Creators/EmulatedGameCardStorageCreator.cs b/src/LibHac/FsService/Creators/EmulatedGameCardStorageCreator.cs index 96160f70..f224cb80 100644 --- a/src/LibHac/FsService/Creators/EmulatedGameCardStorageCreator.cs +++ b/src/LibHac/FsService/Creators/EmulatedGameCardStorageCreator.cs @@ -87,7 +87,7 @@ namespace LibHac.FsService.Creators imageHash.CopyTo(ImageHash); } - public override Result Read(long offset, Span destination) + public override Result ReadImpl(long offset, Span destination) { // In secure mode, if Handle is old and the card's device ID and // header hash are still the same, Handle is updated to the new handle @@ -95,22 +95,22 @@ namespace LibHac.FsService.Creators return GameCard.Read(Handle, offset, destination); } - public override Result Write(long offset, ReadOnlySpan source) + public override Result WriteImpl(long offset, ReadOnlySpan source) { return ResultFs.UnsupportedOperationInRoGameCardStorageWrite.Log(); } - public override Result Flush() + public override Result FlushImpl() { return Result.Success; } - public override Result SetSize(long size) + public override Result SetSizeImpl(long size) { return ResultFs.UnsupportedOperationInRoGameCardStorageSetSize.Log(); } - public override Result GetSize(out long size) + public override Result GetSizeImpl(out long size) { size = 0; diff --git a/src/LibHac/FsSystem/SubStorage.cs b/src/LibHac/FsSystem/SubStorage.cs index c8272bd8..24d4c67d 100644 --- a/src/LibHac/FsSystem/SubStorage.cs +++ b/src/LibHac/FsSystem/SubStorage.cs @@ -62,7 +62,7 @@ namespace LibHac.FsSystem public override Result SetSize(long size) { - if (BaseStorage == null) return ResultFs.Result6902.Log(); + if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log(); // todo: Add IsResizable member // if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();