diff --git a/docs/changelog.md b/docs/changelog.md index a5aa53a87..557afde9f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,26 @@ # Changelog +## 1.12.1 ++ Support was added for the new c-ares resolver in `dns.mitm`. + + Firmware 23.0.0 introduced a new set of commands to the `sfdnsres` service. These commands provide c-ares async support for DNS resolution and are now used by most sysmodules. + + This resulted in host redirection not being applied at all and without warning since we simply were not intercepting the new commands. + + `dns.mitm` now fully reimplements the c-ares serialization code and intercepts the relevant commands. In tandem with the `bsdsocket` sysmodule, we now keep track of resolution queries and redirect their results. ++ Support was added for the new "BatchRead" storage in `fs.mitm`. + + Firmware 23.0.0 introduced a new type of filesystem storage object abstracted by the interface "IStorageForBatchRead". This is a derived class from "IStorage" with the purpose of adding the new "BatchRead" command. + + Anything that uses the filesystem API now attempts to use this type of storage instead of the old one. This is of particular relevance for `qlaunch` and for supporting custom themes which were broken as a consequence of this change. + + `fs.mitm` was updated and extended to not only support the new storage type but also intercept a few newer commands that were previously missing. ++ The patches for the browser applets were redesigned. + + The introduction of these patches in the previous release led to several issues and crashes, notably during media playback in the eshop and within games that use LibAppletOff. + + After extensive analysis and testing it was concluded that the browser applets were running out of memory and still required reducing the memory we reserve for custom sysmodules. + + New patches have been devised and introduced in this release. + + Instead of patching size checks, we now trick the browser applets into thinking there is 1GB of free memory available to them. + + Unused memory is still being reclaimed and discounted from the root heap, but now more realistically. + + The browser engine's heap is now being shrunk with no noticeable downsides to media playback nor web page rendering. + + Thanks to these changes we can now provide 40MB for custom system modules once again. ++ A number of minor issues were fixed and improvements were made, such as: + + Automatic PRODINFO backup was fixed for recent console models that no longer use the ECC device certificate (thanks @chrisbraucker). + + State initialization for SharedMemory and TransferMemory was fixed (thanks @fl0be). + + Compatibility was fixed for Trails in the Sky 2nd Chapter (thanks @masagrator). ++ General system stability improvements to enhance the user's experience. ## 1.12.0 + Support was added for 23.0.0. + Special thanks to @alula for handling the implementation of several kernel changes. diff --git a/emummc/.gitrepo b/emummc/.gitrepo index eea652603..4200412ec 100644 --- a/emummc/.gitrepo +++ b/emummc/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/m4xw/emummc branch = develop - commit = 5b966b6f3f83349ec65066a1877f7f948b48d08c - parent = 7442487ace6b79ddddf2cd0007b8dade8150bf5c + commit = 11a2fd2a25a526c9df92506d69da1f679b1bd997 + parent = 6eb8c3e7ce4209c60bac362f1b88804318cccad2 method = merge cmdver = 0.4.9 diff --git a/emummc/README.md b/emummc/README.md index 752223788..0d921bd3c 100644 --- a/emummc/README.md +++ b/emummc/README.md @@ -2,7 +2,7 @@ *A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** ### Supported Horizon Versions -**1.0.0 - 23.0.0** +**1.0.0 - 23.0.1** ## Features * Arbitrary SDMMC backend selection diff --git a/libraries/.gitrepo b/libraries/.gitrepo index 56e7c065d..e67b1e41e 100644 --- a/libraries/.gitrepo +++ b/libraries/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/Atmosphere-NX/Atmosphere-libs branch = master - commit = aae2da0155a490abd3bfd17a70ccd16bb73c916a - parent = c68e08a101353a89777eb118d6bd21d1dba98ce5 + commit = cf48d23375cf36742876f4b014971b2ebabc6dc8 + parent = ff43bc566adb33c51a43b9ef45b0d3898ad39040 method = merge cmdver = 0.4.9 diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index de463ce6b..360fb69ee 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -358,9 +358,10 @@ namespace ams::kern::board::nintendo::nx { /* NOTE: On 20.0.0+ (and even more-so 21.0.0+) the browser requires much more memory in the applet pool in order to function. */ /* Thus, we have to reduce our extra system memory size by 26 MB to compensate. */ /* NOTE: On 23.0.0+ we are patching memory allocation for each browser applet since there are only 3 of them now. */ - /* Given that the root "Reserved" region is 0x43E000 bytes and the "ReservedTbd" subregion is 0x540000 bytes, we can safely reclaim 9MB.*/ + /* Reclaiming unused memory and lying to the browser about memory limits allows us to go back to 40 MB of extra system memory. */ + /* TODO: Deduplicate post 23.0.0 and pre 20.0.0. For now, this structure helps with readability and is still subject to change. */ if (kern::GetTargetFirmware() >= ams::TargetFirmware_23_0_0) { - constexpr size_t ExtraSystemMemoryForAtmosphere_23_0_0 = 16_MB; + constexpr size_t ExtraSystemMemoryForAtmosphere_23_0_0 = 40_MB; return base_pool_size - ExtraSystemMemoryForAtmosphere_23_0_0 - KTraceBufferSize; } else if (kern::GetTargetFirmware() >= ams::TargetFirmware_21_0_0) { constexpr size_t ExtraSystemMemoryForAtmosphere_21_0_0 = 7_MB; diff --git a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp index 70f9bec97..9c90970a5 100644 --- a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp @@ -104,6 +104,7 @@ namespace ams::hos { Version_22_1_0 = ::ams::TargetFirmware_22_1_0, Version_22_5_0 = ::ams::TargetFirmware_22_5_0, Version_23_0_0 = ::ams::TargetFirmware_23_0_0, + Version_23_0_1 = ::ams::TargetFirmware_23_0_1, Version_Current = ::ams::TargetFirmware_Current, diff --git a/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp b/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp index b9bd3a0bf..2435b8801 100644 --- a/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp @@ -167,8 +167,13 @@ namespace ams::socket { int ai_family; int ai_socktype; int ai_protocol; + #if defined(ATMOSPHERE_OS_WINDOWS) + int ai_addrlen; + void *ai_addr; + #else socklen_t ai_addrlen; struct sockaddr *ai_addr; + #endif struct ares_addrinfo_node *ai_next; }; diff --git a/libraries/libstratosphere/source/util/zstd.inc b/libraries/libstratosphere/source/util/zstd.inc index 72ea32f00..58b47ded8 100644 --- a/libraries/libstratosphere/source/util/zstd.inc +++ b/libraries/libstratosphere/source/util/zstd.inc @@ -46857,14 +46857,18 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, /*-************************************* * Dependencies ***************************************/ -/* qsort_r is an extension. */ -#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \ - defined(__CYGWIN__) || defined(__MSYS__) -#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */ -#define _GNU_SOURCE -#endif +/* qsort_r is an extension. + * + * Android NDK does not ship qsort_r(). + */ +#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__) +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# endif #endif +#define __STDC_WANT_LIB_EXT1__ 1 /* request C11 Annex K, which includes qsort_s() */ + #include /* fprintf */ #include /* malloc, free, qsort_r */ @@ -46875,6 +46879,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, # define ZDICT_STATIC_LINKING_ONLY #endif +/**** skipping file: ../common/debug.h ****/ /**** skipping file: ../common/mem.h ****/ /**** skipping file: ../common/pool.h ****/ /**** skipping file: ../common/threading.h ****/ @@ -47531,6 +47536,31 @@ void COVER_dictSelectionFree(COVER_dictSelection_t selection); #define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB)) #define COVER_DEFAULT_SPLITPOINT 1.0 +/** + * Select the qsort() variant used by cover + */ +#define ZDICT_QSORT_MIN 0 +#define ZDICT_QSORT_C90 ZDICT_QSORT_MIN +#define ZDICT_QSORT_GNU 1 +#define ZDICT_QSORT_APPLE 2 +#define ZDICT_QSORT_MSVC 3 +#define ZDICT_QSORT_C11 ZDICT_QSORT_MAX +#define ZDICT_QSORT_MAX 4 + +#ifndef ZDICT_QSORT +# if defined(__APPLE__) +# define ZDICT_QSORT ZDICT_QSORT_APPLE /* uses qsort_r() with a different order for parameters */ +# elif (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__) +# define ZDICT_QSORT ZDICT_QSORT_GNU /* uses qsort_r() */ +# elif defined(_WIN32) && defined(_MSC_VER) +# define ZDICT_QSORT ZDICT_QSORT_MSVC /* uses qsort_s() with a different order for parameters */ +# elif defined(STDC_LIB_EXT1) && (STDC_LIB_EXT1 > 0) /* C11 Annex K */ +# define ZDICT_QSORT ZDICT_QSORT_C11 /* uses qsort_s() */ +# else +# define ZDICT_QSORT ZDICT_QSORT_C90 /* uses standard qsort() which is not re-entrant (requires global variable) */ +# endif +#endif + /*-************************************* * Console display ***************************************/ @@ -47712,8 +47742,8 @@ typedef struct { unsigned d; } COVER_ctx_t; -#if !defined(_GNU_SOURCE) && !defined(__APPLE__) && !defined(_MSC_VER) -/* C90 only offers qsort() that needs a global context. */ +#if ZDICT_QSORT == ZDICT_QSORT_C90 +/* Use global context for non-reentrant sort functions */ static COVER_ctx_t *g_coverCtx = NULL; #endif @@ -47759,9 +47789,9 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) { /** * Same as COVER_cmp() except ties are broken by pointer value */ -#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__) +#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE) static int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) { -#elif defined(_GNU_SOURCE) +#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11) static int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) { #else /* C90 fallback.*/ static int COVER_strict_cmp(const void *lp, const void *rp) { @@ -47775,9 +47805,9 @@ static int COVER_strict_cmp(const void *lp, const void *rp) { /** * Faster version for d <= 8. */ -#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__) +#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE) static int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) { -#elif defined(_GNU_SOURCE) +#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11) static int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) { #else /* C90 fallback.*/ static int COVER_strict_cmp8(const void *lp, const void *rp) { @@ -47794,26 +47824,28 @@ static int COVER_strict_cmp8(const void *lp, const void *rp) { * Hopefully when C11 become the norm, we will be able * to clean it up. */ -static void stableSort(COVER_ctx_t *ctx) { -#if defined(__APPLE__) +static void stableSort(COVER_ctx_t *ctx) +{ + DEBUG_STATIC_ASSERT(ZDICT_QSORT_MIN <= ZDICT_QSORT && ZDICT_QSORT <= ZDICT_QSORT_MAX); +#if (ZDICT_QSORT == ZDICT_QSORT_APPLE) qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx, (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); -#elif defined(_GNU_SOURCE) +#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32), (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), ctx); -#elif defined(_WIN32) && defined(_MSC_VER) +#elif (ZDICT_QSORT == ZDICT_QSORT_MSVC) + qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), + ctx); +#elif (ZDICT_QSORT == ZDICT_QSORT_C11) qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32), (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), ctx); -#elif defined(__OpenBSD__) - g_coverCtx = ctx; - mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32), - (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); #else /* C90 fallback.*/ g_coverCtx = ctx; - /* TODO(cavalcanti): implement a reentrant qsort() when is not available. */ + /* TODO(cavalcanti): implement a reentrant qsort() when _r is not available. */ qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); #endif diff --git a/libraries/libvapours/include/vapours/ams/ams_api_version.h b/libraries/libvapours/include/vapours/ams/ams_api_version.h index 2fd987485..dd2b85fc4 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 12 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 23 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 -#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 109405664..d16f94e70 100644 --- a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h +++ b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h @@ -102,8 +102,9 @@ #define ATMOSPHERE_TARGET_FIRMWARE_22_1_0 ATMOSPHERE_TARGET_FIRMWARE(22, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_22_5_0 ATMOSPHERE_TARGET_FIRMWARE(22, 5, 0) #define ATMOSPHERE_TARGET_FIRMWARE_23_0_0 ATMOSPHERE_TARGET_FIRMWARE(23, 0, 0) +#define ATMOSPHERE_TARGET_FIRMWARE_23_0_1 ATMOSPHERE_TARGET_FIRMWARE(23, 0, 1) -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_23_0_0 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_23_0_1 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT @@ -198,6 +199,7 @@ namespace ams { TargetFirmware_22_1_0 = ATMOSPHERE_TARGET_FIRMWARE_22_1_0, TargetFirmware_22_5_0 = ATMOSPHERE_TARGET_FIRMWARE_22_5_0, TargetFirmware_23_0_0 = ATMOSPHERE_TARGET_FIRMWARE_23_0_0, + TargetFirmware_23_0_1 = ATMOSPHERE_TARGET_FIRMWARE_23_0_1, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, diff --git a/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp b/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp index 1e419f8f8..c56b3f47b 100644 --- a/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp @@ -256,7 +256,6 @@ namespace ams::mitm { bool IsValid(const CalibrationInfo &cal) { return IsValidHeader(cal) && IsValid(cal.GetBlock()) && - IsValid(cal.GetBlock()) && IsValid(cal.GetBlock()) && IsValid(cal.GetBlock()) && cal.GetBlock().ssl_certificate_size <= sizeof(cal.GetBlock().ssl_certificate) && @@ -267,7 +266,8 @@ namespace ams::mitm { IsValidSerialNumber(cal); } - bool ContainsCorrectDeviceId(const EccB233DeviceCertificateBlock &block, u64 device_id) { + template + bool ContainsCorrectDeviceId(const Block &block, u64 device_id) { static constexpr size_t DeviceIdOffset = 0xC6; char found_device_id_str[sizeof("0011223344556677")] = {}; ON_SCOPE_EXIT { std::memset(found_device_id_str, 0, sizeof(found_device_id_str)); }; @@ -279,7 +279,14 @@ namespace ams::mitm { } bool ContainsCorrectDeviceId(const CalibrationInfo &cal) { - return ContainsCorrectDeviceId(cal.GetBlock(), exosphere::GetDeviceId()); + const auto &ecc = cal.GetBlock(); + if (!IsBlank(ecc)) { + return IsValid(ecc) && ContainsCorrectDeviceId(ecc, exosphere::GetDeviceId()); + } + + /* Newer consoles may leave the ECC certificate unprogrammed. */ + const auto &rsa = cal.GetBlock(); + return !IsBlank(rsa) && IsValid(rsa) && ContainsCorrectDeviceId(rsa, exosphere::GetDeviceId()); } bool IsValidForSecureBackup(const CalibrationInfo &cal) { diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp index 0d514c6ce..2e7f7e091 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp @@ -28,11 +28,11 @@ namespace ams::mitm::socket::resolver { std::string hostname; ams::socket::InAddrT redirect_addr; u16 redirect_port; - const struct ams::socket::ares_addrinfo_hints *hint; + bool use_hint; + struct ams::socket::ares_addrinfo_hints hint; }; std::map> g_ares_addr_info_queries; - ssize_t g_current_ares_addr_info_query_id; } @@ -100,21 +100,17 @@ namespace ams::mitm::socket::resolver { return result; } - ssize_t QueueAresAddrInfoQuery(const char *hostname, ams::socket::InAddrT redirect_addr, u16 redirect_port, const struct ams::socket::ares_addrinfo_hints *hint) { - ssize_t query_id = g_current_ares_addr_info_query_id; - + void QueueAresAddrInfoQuery(ssize_t query_id, const char *hostname, ams::socket::InAddrT redirect_addr, u16 redirect_port, const struct ams::socket::ares_addrinfo_hints *hint) { AresAddrInfoQuery query; query.hostname = hostname; query.redirect_addr = redirect_addr; query.redirect_port = redirect_port; - query.hint = hint; - + query.use_hint = hint != nullptr; + if (query.use_hint) { + query.hint = *hint; + } + g_ares_addr_info_queries.emplace(query_id, std::make_unique(query)); - - /* NOTE: This really just increases ad infinitum. Should we bother checking it? */ - ++g_current_ares_addr_info_query_id; - - return query_id; } ssize_t DequeueAresAddrInfoQuery(u8 * const dst, size_t dst_size, u32 query_id) { @@ -128,7 +124,7 @@ namespace ams::mitm::socket::resolver { } if (query == nullptr) { - return 0; + return -1; } struct ams::socket::ares_addrinfo_node node = { @@ -141,8 +137,8 @@ namespace ams::mitm::socket::resolver { .ai_next = nullptr, }; - if (query->hint != nullptr) { - std::memcpy(reinterpret_cast(std::addressof(node.ai_flags)), reinterpret_cast(query->hint), sizeof(struct ams::socket::ares_addrinfo_hints)); + if (query->use_hint) { + std::memcpy(std::addressof(node.ai_flags), std::addressof(query->hint), sizeof(query->hint)); } switch (node.ai_family) { @@ -178,17 +174,19 @@ namespace ams::mitm::socket::resolver { const auto result = serializer::DNSSerializer::ToBuffer(dst, dst_size, ai); AMS_ABORT_UNLESS(result >= 0); - g_ares_addr_info_queries.erase(query_id); + g_ares_addr_info_queries.erase(static_cast(query_id)); return result; } - void CancelAresAddrInfoQuery(u32 query_id) { + bool CancelAresAddrInfoQuery(u32 query_id) { for (auto it = g_ares_addr_info_queries.begin(); it != g_ares_addr_info_queries.end(); ++it) { if (it->first == static_cast(query_id)) { g_ares_addr_info_queries.erase(it); - break; + return true; } } + + return false; } Result ResolverImpl::GetHostByNameRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &name, sf::Out out_host_error, sf::Out out_errno, const sf::OutBuffer &out_hostent, sf::Out out_size) { @@ -321,8 +319,6 @@ namespace ams::mitm::socket::resolver { } Result ResolverImpl::QueryAddrInfoRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &node, const sf::InAutoSelectBuffer &srv, const sf::InAutoSelectBuffer &serialized_hint, sf::Out out_query_id, u32 fd, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_retval, sf::Out out_errno) { - AMS_UNUSED(client_pid, fd, options_version, options, num_options); - const char *hostname = reinterpret_cast(node.GetPointer()); LogDebug("[%016lx]: QueryAddrInfoRequestWithOptions(%s, %s)\n", m_client_info.program_id.value, hostname, reinterpret_cast(srv.GetPointer())); @@ -341,7 +337,7 @@ namespace ams::mitm::socket::resolver { } } - LogDebug("[%016lx]: Queueing redirection %s:%u to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, port, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF); + LogDebug("[%016lx]: Queueing query for redirecting %s:%u to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, port, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF); const bool use_hint = serialized_hint.GetPointer() != nullptr; struct ams::socket::ares_addrinfo_hints hint = {}; @@ -349,30 +345,39 @@ namespace ams::mitm::socket::resolver { AMS_ABORT_UNLESS(serializer::DNSSerializer::FromBuffer(hint, serialized_hint.GetPointer(), serialized_hint.GetSize()) >= 0); } - const auto query_id = QueueAresAddrInfoQuery(hostname, redirect_addr, port, use_hint ? std::addressof(hint) : nullptr); - - LogDebug("[%016lx]: Queued query with id 0x%lx\n", m_client_info.program_id.value, query_id); - - /* Forward the query. The provided socket EventFd must be signalled by having bsdsocket write 1 to the associated socket. */ - /* This is fine though, we only care about replacing with our redirection during fetch. */ + /* Forward to session. The provided socket EventFd must be signalled by having bsdsocket write 1 to the associated socket. */ + /* This is fine though, we only care about replacing with our redirection during fetch. */ + /* Additionally, a failure at this point can be safely handled by bsdsocket, it simply won't create a new query. */ R_TRY(sfdnsresQueryAddrInfoRequestWithOptionsFwd(m_forward_service.get(), static_cast(client_pid.GetValue().value), node.GetPointer(), node.GetSize(), srv.GetPointer(), srv.GetSize(), serialized_hint.GetPointer(), serialized_hint.GetSize(), reinterpret_cast(out_query_id.GetPointer()), fd, options_version, options.GetPointer(), options.GetSize(), num_options, reinterpret_cast(out_retval.GetPointer()), reinterpret_cast(out_errno.GetPointer()))); - /* Replace with our own query. */ - *out_query_id = query_id; - *out_retval = 0; - *out_errno = 0; + /* If no errors were returned, trust the id bsdsocket generated and queue the query. */ + /* When bsdsocket's queue is full, retval and errno will reflect that and the returned query id will be -1. */ + /* This is expected by the client. We must drop this query and let the client see the errors for it to schedule a new query. */ + if ((*out_retval == 0) && (*out_errno == 0)) { + ssize_t query_id = static_cast(*out_query_id); + QueueAresAddrInfoQuery(query_id, hostname, redirect_addr, port, use_hint ? std::addressof(hint) : nullptr); + LogDebug("[%016lx]: Queued query with id 0x%lx\n", m_client_info.program_id.value, query_id); + } else { + LogDebug("[%016lx]: Dropping last query, queue is full\n", m_client_info.program_id.value); + } R_SUCCEED(); } Result ResolverImpl::FetchAddrInfoRequestWithOptions(const sf::ClientProcessId &client_pid, u32 query_id, u32 version, const sf::OutAutoSelectBuffer &out_addrinfo, sf::Out out_size, sf::Out out_retval, sf::Out out_errno) { - AMS_UNUSED(client_pid, version); - - LogDebug("[%016lx]: FetchAddrInfoRequestWithOptions(%d)\n", m_client_info.program_id.value, query_id); + LogDebug("[%016lx]: FetchAddrInfoRequestWithOptions(0x%x)\n", m_client_info.program_id.value, query_id); const auto size = DequeueAresAddrInfoQuery(out_addrinfo.GetPointer(), out_addrinfo.GetSize(), query_id); + + /* If we don't have this query queued, then the hostname is not in the hosts file. Forward to session. */ + R_UNLESS(size >= 0, sm::mitm::ResultShouldForwardToSession()); - LogDebug("[%016lx]: Dequeued query with size 0x%lx\n", m_client_info.program_id.value, size); + LogDebug("[%016lx]: Dequeued query 0x%x with size 0x%lx\n", m_client_info.program_id.value, query_id, size); + + /* Forward to session. The socket EventFd associated with this query must be cleared by having bsdsocket write 0 to the socket. */ + /* However, we want to keep our redirection, so we pass nullptr to bsdsocket forcing the command to end early with an error. */ + /* We discard the error and replace the output, pretending the command was successful while returning our redirected addrinfo to the client instead. */ + R_DISCARD(sfdnsresFetchAddrInfoRequestWithOptionsFwd(m_forward_service.get(), static_cast(client_pid.GetValue().value), query_id, version, nullptr, 0, reinterpret_cast(out_size.GetPointer()), reinterpret_cast(out_retval.GetPointer()), reinterpret_cast(out_errno.GetPointer()))); *out_size = size; *out_retval = 0; @@ -382,11 +387,18 @@ namespace ams::mitm::socket::resolver { } Result ResolverImpl::CancelQuery(const sf::ClientProcessId &client_pid, u32 query_id) { - AMS_UNUSED(client_pid); - - LogDebug("[%016lx]: CancelQuery(%d)\n", m_client_info.program_id.value, query_id); + LogDebug("[%016lx]: CancelQuery(0x%x)\n", m_client_info.program_id.value, query_id); - CancelAresAddrInfoQuery(query_id); + const auto found = CancelAresAddrInfoQuery(query_id); + + /* If we don't have this query queued, then we never intercepted it. Forward to session. */ + R_UNLESS(found, sm::mitm::ResultShouldForwardToSession()); + + LogDebug("[%016lx]: Cancelled query 0x%x\n", m_client_info.program_id.value, query_id); + + /* Forward to session. Ensures that bsdsocket cleans up. */ + /* We still want to discard any errors and return success in case this was a query we had queued. */ + R_DISCARD(sfdnsresCancelQueryFwd(m_forward_service.get(), static_cast(client_pid.GetValue().value), query_id)); R_SUCCEED(); } diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp index 314f2db8f..470753f77 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp @@ -51,10 +51,12 @@ namespace ams::mitm::fs { /* Unknown heap sensitivity. */ { 0x01002C9022770000, 16_MB, 0_MB }, - /* Trails in the Sky 2nd Chapter. */ + /* Trails in the Sky 2nd Chapter (Global, Asia and Japan versions). */ /* Requirement ~16 MB.*/ /* No particular heap sensitivity. */ { 0x01007A2027548000, 8_MB, 0_MB }, + { 0x0100E8B028B54000, 8_MB, 0_MB }, + { 0x01002270268E0000, 8_MB, 0_MB }, /* STAR WARS: Knights of the Old Republic II: The Sith Lords. */ /* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */ diff --git a/stratosphere/loader/source/ldr_embedded_web_patches.inc b/stratosphere/loader/source/ldr_embedded_web_patches.inc index 825123005..53e476c81 100644 --- a/stratosphere/loader/source/ldr_embedded_web_patches.inc +++ b/stratosphere/loader/source/ldr_embedded_web_patches.inc @@ -15,41 +15,37 @@ */ /* Breakdown of each patch in order: */ -/* #1 - Patch the 0xDEEF000 size check branch to NOP. */ +/* #1 - Set TotalAvailableMemorySize to 1GB. */ /* #2 - Change the root heap "Reserved" region allocation size from 0x43E000 to 0. */ -/* #3 - Change the root heap "Scene" size from 0x4580000 to 0x4040000. */ -/* #4 - Change the scene heap "ReservedTbd" region allocation size from 0x540000 to 0. */ -/* #5 - Patch the linking of "ReservedTbd" to the parent heap with a NOP. */ -/* #6 - Patch the initial memory block allocation size from 0xB400000 to 0xAC00000. */ -/* #7 - Patch the initial memory block initialization size from 0xB400000 to 0xAC00000. */ +/* #3 - Patch the initial memory block allocation size from 0xB400000 to 0xB000000. */ +/* #4 - Patch the initial memory block heap size from 0xB400000 to 0xB000000. */ +/* #5 - Patch the browser engine memory capacity from 0xAA00000 to 0x9000000. */ +/* #6 - Patch the browser engine memory allocation size from 0xAA00000 to 0x9000000. */ constexpr inline const EmbeddedPatchEntry SystemWebMemoryPatches_23_0_0[] = { - { 0x861DD4, "\x1F\x20\x03\xD5", 4 }, + { 0x6113A8, "\x09\x00\xA8\xD2", 4 }, { 0x861E80, "\x02\x00\x80\x52", 4 }, - { 0x861E6C, "\x82\x80\xA0\x52", 4 }, - { 0x8C1718, "\x02\x00\x80\x52", 4 }, - { 0x8C172C, "\x1F\x20\x03\xD5", 4 }, - { 0x861D44, "\x01\x58\xA1\x52", 4 }, - { 0x861D5C, "\x03\x58\xA1\x52", 4 }, + { 0x861D44, "\x01\x60\xA1\x52", 4 }, + { 0x861D5C, "\x03\x60\xA1\x52", 4 }, + { 0x8623D0, "\x01\x20\xA1\x52", 4 }, + { 0x862498, "\x01\x20\xA1\x52", 4 }, }; constexpr inline const EmbeddedPatchEntry OpenWebMemoryPatches_23_0_0[] = { - { 0x828DBC, "\x1F\x20\x03\xD5", 4 }, + { 0x611428, "\x09\x00\xA8\xD2", 4 }, { 0x828E68, "\x02\x00\x80\x52", 4 }, - { 0x828E54, "\x82\x80\xA0\x52", 4 }, - { 0x74C564, "\x02\x00\x80\x52", 4 }, - { 0x74C578, "\x1F\x20\x03\xD5", 4 }, - { 0x828D2C, "\x01\x58\xA1\x52", 4 }, - { 0x828D44, "\x03\x58\xA1\x52", 4 }, + { 0x828D2C, "\x01\x60\xA1\x52", 4 }, + { 0x828D44, "\x03\x60\xA1\x52", 4 }, + { 0x8293B8, "\x01\x20\xA1\x52", 4 }, + { 0x829480, "\x01\x20\xA1\x52", 4 }, }; constexpr inline const EmbeddedPatchEntry OfflineWebMemoryPatches_23_0_0[] = { - { 0x130698, "\x1F\x20\x03\xD5", 4 }, + { 0x6DE0DC, "\x09\x00\xA8\xD2", 4 }, { 0x130744, "\x02\x00\x80\x52", 4 }, - { 0x130730, "\x82\x80\xA0\x52", 4 }, - { 0x4D728, "\x02\x00\x80\x52", 4 }, - { 0x4D738, "\x1F\x20\x03\xD5", 4 }, - { 0x130614, "\x01\x58\xA1\x52", 4 }, - { 0x130624, "\x02\x58\xA1\x52", 4 }, + { 0x130614, "\x01\x60\xA1\x52", 4 }, + { 0x130624, "\x02\x60\xA1\x52", 4 }, + { 0x130C30, "\x01\x20\xA1\x52", 4 }, + { 0x130CD0, "\x01\x20\xA1\x52", 4 }, }; constexpr inline const EmbeddedPatch WebMemoryPatches[] = {