From 3545c0aac2cdfc1f6f897e8c669a8e33358b3ece Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 29 Apr 2022 16:13:34 -0700 Subject: [PATCH] ams: fs accuracy fixes, bump to 1.3.2 --- docs/changelog.md | 9 ++++++++ ...ystem_aes_ctr_counter_extended_storage.hpp | 8 ++++++- .../fssystem_i_hash_256_generator.hpp | 8 +++---- ...ssystem_integrity_verification_storage.hpp | 11 +++------ .../fssystem/fssystem_sha_hash_generator.hpp | 8 +++++-- .../include/stratosphere/hos/hos_types.hpp | 1 + ...ystem_aes_ctr_counter_extended_storage.cpp | 23 ++++++++++++------- ...ssystem_integrity_verification_storage.cpp | 12 ++++++---- .../include/vapours/ams/ams_api_version.h | 4 ++-- .../include/vapours/ams/ams_target_firmware.h | 4 +++- 10 files changed, 57 insertions(+), 31 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 4ad8b030d..1ff30187e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,13 @@ # Changelog +## 1.3.2 ++ Support was improved for 14.0.0+. + + `loader` was updated to reflect the latest official behaviors. + + `ro` was updated to reflect the latest official behaviors. ++ A number of minor issues were fixed and improvements were made, including: + + A memory leak was fixed in filesystem path management; this could cause a crash when launching games ~100 times, or when deleting/re-downloading games. + + A bug was fixed that could cause threads to not see a newly signaled semaphore. + + A number of minor inaccuracies were fixed in the updated FileSystem APIs. ++ General system stability improvements to enhance the user's experience. ## 1.3.1 + Support was added for 14.1.0. + A number of minor under the hood improvements to accuracy were made to better reflect latest official system module behavior, particularly around FS apis. diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp index 0043cbee8..fe6e3339e 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_aes_ctr_counter_extended_storage.hpp @@ -42,8 +42,14 @@ namespace ams::fssystem { }; struct Entry { + enum class Encryption : u8 { + Encrypted = 0, + NotEncrypted = 1, + }; + u8 offset[sizeof(s64)]; - s32 reserved; + Encryption encryption_value; + u8 reserved[3]; s32 generation; void SetOffset(s64 value) { diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_i_hash_256_generator.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_i_hash_256_generator.hpp index 027a5fcd9..46c0bd8c3 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_i_hash_256_generator.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_i_hash_256_generator.hpp @@ -60,8 +60,8 @@ namespace ams::fssystem { constexpr IHash256GeneratorFactory() = default; virtual constexpr ~IHash256GeneratorFactory() { /* ... */ } - std::unique_ptr Create() { - return this->DoCreate(); + Result Create(std::unique_ptr *out) { + return this->DoCreate(out); } void GenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) { @@ -73,11 +73,11 @@ namespace ams::fssystem { return this->DoGenerateHash(dst, dst_size, src, src_size); } protected: - virtual std::unique_ptr DoCreate() = 0; + virtual Result DoCreate(std::unique_ptr *out) = 0; virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) = 0; }; - /* ACCURATE_TO_VERSION: 13.4.0.0 */ + /* ACCURATE_TO_VERSION: 14.3.0.0 */ class IHash256GeneratorFactorySelector { public: constexpr IHash256GeneratorFactorySelector() = default; diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_integrity_verification_storage.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_integrity_verification_storage.hpp index b90e87e69..fdab3bd3b 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_integrity_verification_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_integrity_verification_storage.hpp @@ -52,7 +52,7 @@ namespace ams::fssystem { IntegrityVerificationStorage() : m_verification_block_size(0), m_verification_block_order(0), m_upper_layer_verification_block_size(0), m_upper_layer_verification_block_order(0), m_buffer_manager(nullptr), m_salt(util::nullopt) { /* ... */ } virtual ~IntegrityVerificationStorage() override { this->Finalize(); } - Result Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks); + void Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks); void Finalize(); virtual Result Read(s64 offset, void *buffer, size_t size) override; @@ -66,9 +66,8 @@ namespace ams::fssystem { virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override; using IStorage::OperateRange; - void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size) const { - auto generator = m_hash_generator_factory->Create(); - return this->CalcBlockHash(out, buffer, block_size, generator); + void CalcBlockHash(BlockHash *out, const void *buffer, std::unique_ptr &generator) const { + return this->CalcBlockHash(out, buffer, static_cast(m_verification_block_size), generator); } s64 GetBlockSize() const { @@ -81,10 +80,6 @@ namespace ams::fssystem { void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size, std::unique_ptr &generator) const; - void CalcBlockHash(BlockHash *out, const void *buffer, std::unique_ptr &generator) const { - return this->CalcBlockHash(out, buffer, static_cast(m_verification_block_size), generator); - } - Result IsCleared(bool *is_cleared, const BlockHash &hash); private: static void SetValidationBit(BlockHash *hash) { diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_sha_hash_generator.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_sha_hash_generator.hpp index a5aae0870..36ff4eb66 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_sha_hash_generator.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_sha_hash_generator.hpp @@ -56,8 +56,12 @@ namespace ams::fssystem { public: constexpr ShaHashGeneratorFactory() = default; protected: - virtual std::unique_ptr DoCreate() override { - return std::unique_ptr(new ShaHashGenerator()); + virtual Result DoCreate(std::unique_ptr *out) override { + auto generator = std::unique_ptr(new ShaHashGenerator()); + R_UNLESS(generator != nullptr, fs::ResultAllocationMemoryFailedNew()); + + *out = std::move(generator); + R_SUCCEED(); } virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) override { diff --git a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp index 39de0fe70..b55be4960 100644 --- a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp @@ -71,6 +71,7 @@ namespace ams::hos { Version_13_2_1 = ::ams::TargetFirmware_13_2_1, Version_14_0_0 = ::ams::TargetFirmware_14_0_0, Version_14_1_0 = ::ams::TargetFirmware_14_1_0, + Version_14_1_1 = ::ams::TargetFirmware_14_1_1, Version_Current = ::ams::TargetFirmware_Current, diff --git a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp index d11455167..88d1bb464 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp @@ -87,7 +87,11 @@ namespace ams::fssystem { AMS_ASSERT(decryptor != nullptr); /* Initialize the bucket tree table. */ - R_TRY(m_table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count)); + if (entry_count > 0) { + R_TRY(m_table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count)); + } else { + m_table.Initialize(NodeSize, 0); + } /* Set members. */ m_data_storage = data_storage; @@ -174,15 +178,18 @@ namespace ams::fssystem { const auto cur_size = static_cast(std::min(remaining_size, data_size)); AMS_ASSERT(cur_size <= size); - /* Make the CTR for the data we're decrypting. */ - const auto counter_offset = m_counter_offset + cur_entry_offset + data_offset; - NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast(cur_entry.generation), .secure_value = m_secure_value } }; + /* If necessary, perform decryption. */ + if (cur_entry.encryption_value == Entry::Encryption::Encrypted) { + /* Make the CTR for the data we're decrypting. */ + const auto counter_offset = m_counter_offset + cur_entry_offset + data_offset; + NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast(cur_entry.generation), .secure_value = m_secure_value } }; - u8 iv[IvSize]; - AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset); + u8 iv[IvSize]; + AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset); - /* Decrypt. */ - m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize); + /* Decrypt. */ + m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize); + } /* Advance. */ cur_data += cur_size; diff --git a/libraries/libstratosphere/source/fssystem/fssystem_integrity_verification_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_integrity_verification_storage.cpp index c60617cb9..6493c5a5f 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_integrity_verification_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_integrity_verification_storage.cpp @@ -17,7 +17,7 @@ namespace ams::fssystem { - Result IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks) { + void IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks) { /* Validate preconditions. */ AMS_ASSERT(verif_block_size >= HashSize); AMS_ASSERT(bm != nullptr); @@ -61,7 +61,6 @@ namespace ams::fssystem { m_is_real_data = is_real_data; m_is_writable = is_writable; m_allow_cleared_blocks = allow_cleared_blocks; - R_SUCCEED(); } void IntegrityVerificationStorage::Finalize() { @@ -120,7 +119,8 @@ namespace ams::fssystem { Result verify_hash_result = ResultSuccess(); /* Create hash generator. */ - auto generator = m_hash_generator_factory->Create(); + std::unique_ptr generator = nullptr; + R_TRY(m_hash_generator_factory->Create(std::addressof(generator))); /* Prepare to validate the signatures. */ const auto signature_count = size >> m_verification_block_order; @@ -221,7 +221,9 @@ namespace ams::fssystem { PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash)); const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash)); - auto generator = m_hash_generator_factory->Create(); + /* Create hash generator. */ + std::unique_ptr generator = nullptr; + R_TRY(m_hash_generator_factory->Create(std::addressof(generator))); while (updated_count < signature_count) { const auto cur_count = std::min(buffer_count, signature_count - updated_count); @@ -326,7 +328,7 @@ namespace ams::fssystem { R_TRY(m_hash_storage.Read(sign_offset, buf.get(), sign_size)); /* Clear the signature. */ - /* This sets all bytes to FF, with the verification bit cleared. */ + /* This flips all bits other than the verification bit. */ for (auto i = 0; i < sign_size; ++i) { buf[i] ^= ((i + 1) % HashSize == 0 ? 0x7F : 0xFF); } diff --git a/libraries/libvapours/include/vapours/ams/ams_api_version.h b/libraries/libvapours/include/vapours/ams/ams_api_version.h index aec8d1981..bcbfe3f73 100644 --- a/libraries/libvapours/include/vapours/ams/ams_api_version.h +++ b/libraries/libvapours/include/vapours/ams/ams_api_version.h @@ -17,10 +17,10 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MINOR 3 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 14 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1 -#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1 diff --git a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h index 80aad7122..8a755fd9f 100644 --- a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h +++ b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h @@ -69,8 +69,9 @@ #define ATMOSPHERE_TARGET_FIRMWARE_13_2_1 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 1) #define ATMOSPHERE_TARGET_FIRMWARE_14_0_0 ATMOSPHERE_TARGET_FIRMWARE(14, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_14_1_0 ATMOSPHERE_TARGET_FIRMWARE(14, 1, 0) +#define ATMOSPHERE_TARGET_FIRMWARE_14_1_1 ATMOSPHERE_TARGET_FIRMWARE(14, 1, 1) -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_14_1_0 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_14_1_1 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT @@ -132,6 +133,7 @@ namespace ams { TargetFirmware_13_2_1 = ATMOSPHERE_TARGET_FIRMWARE_13_2_1, TargetFirmware_14_0_0 = ATMOSPHERE_TARGET_FIRMWARE_14_0_0, TargetFirmware_14_1_0 = ATMOSPHERE_TARGET_FIRMWARE_14_1_0, + TargetFirmware_14_1_1 = ATMOSPHERE_TARGET_FIRMWARE_14_1_1, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,