diff --git a/CMakeLists.txt b/CMakeLists.txt index e288717..64d5b10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,50 +561,6 @@ target_link_libraries(mocktail_bionic_abi_exports PRIVATE Threads::Threads ) -include(CheckCXXSourceCompiles) -include(CheckIncludeFileCXX) -include(CMakePushCheckState) - -check_include_file_cxx(execinfo.h MOCKTAIL_HAVE_EXECINFO_H) -if(NOT MOCKTAIL_HAVE_EXECINFO_H) - message(FATAL_ERROR - "execinfo.h is required for crash diagnostics; on musl install " - "libexecinfo-devel" - ) -endif() - -set(MOCKTAIL_EXECINFO_LINK_LIBRARY "") -set(_mocktail_execinfo_link_probe [=[ - #include - int main() { - void* frames[1] = {}; - const int count = backtrace(frames, 1); - return backtrace_symbols(frames, count) == nullptr; - } -]=]) -check_cxx_source_compiles( - "${_mocktail_execinfo_link_probe}" - MOCKTAIL_EXECINFO_IN_HOST_LIBC -) -if(NOT MOCKTAIL_EXECINFO_IN_HOST_LIBC) - find_library(MOCKTAIL_EXECINFO_LIBRARY NAMES execinfo REQUIRED) - cmake_push_check_state(RESET) - set(CMAKE_REQUIRED_LIBRARIES "${MOCKTAIL_EXECINFO_LIBRARY}") - check_cxx_source_compiles( - "${_mocktail_execinfo_link_probe}" - MOCKTAIL_EXECINFO_IN_EXTERNAL_LIBRARY - ) - cmake_pop_check_state() - if(NOT MOCKTAIL_EXECINFO_IN_EXTERNAL_LIBRARY) - message(FATAL_ERROR - "execinfo.h is available, but backtrace and backtrace_symbols cannot " - "be linked" - ) - endif() - set(MOCKTAIL_EXECINFO_LINK_LIBRARY "${MOCKTAIL_EXECINFO_LIBRARY}") -endif() -unset(_mocktail_execinfo_link_probe) - add_library(mocktail_legacy_runtime STATIC src/legacy/legacy_runtime.cc src/runtime/roblox_text_input_jni_bridge.cc @@ -629,7 +585,6 @@ target_link_libraries(mocktail_legacy_runtime PRIVATE libc_shim mocktail_window mocktail_graphics_foundation - ${MOCKTAIL_EXECINFO_LINK_LIBRARY} ) target_compile_definitions(mocktail_legacy_runtime PRIVATE "MOCKTAIL_DEFAULT_COMPATIBILITY_MANIFEST=\"${MOCKTAIL_DEFAULT_COMPATIBILITY_MANIFEST}\"" diff --git a/config/upstream_dependencies.json b/config/upstream_dependencies.json index eb796fd..b8f9b19 100644 --- a/config/upstream_dependencies.json +++ b/config/upstream_dependencies.json @@ -32,7 +32,7 @@ "mode": "vendored-patched-snapshot", "url": "https://github.com/minecraft-linux/mcpelauncher-linker.git", "upstream_commit": "1ac3ea6c1cf4f73a84d73f0bff510fba94a7d0f2", - "vendor_tree": "fca44d85e3773c135ccfc603b14abdf6aeb8efd1", + "vendor_tree": "0637221e48f382ec8d0bc701385f4b10bcd07a65", "patch": "third_party/patches/mcpelauncher-linker.patch", "nested_sources": { "android_bionic": { diff --git a/include/compat/bionic_host_libc_runtime.h b/include/compat/bionic_host_libc_runtime.h index 5c8d44c..be55994 100644 --- a/include/compat/bionic_host_libc_runtime.h +++ b/include/compat/bionic_host_libc_runtime.h @@ -14,16 +14,16 @@ namespace mocktail::compat { // Android uses size_t fields here; glibc uses int and musl has no equivalent. // An all-zero fallback means unknown, not zero usage. struct BionicMallinfoSnapshot { - size_t arena = 0; - size_t ordblks = 0; - size_t smblks = 0; - size_t hblks = 0; - size_t hblkhd = 0; - size_t usmblks = 0; - size_t fsmblks = 0; - size_t uordblks = 0; - size_t fordblks = 0; - size_t keepcost = 0; + size_t arena; + size_t ordblks; + size_t smblks; + size_t hblks; + size_t hblkhd; + size_t usmblks; + size_t fsmblks; + size_t uordblks; + size_t fordblks; + size_t keepcost; }; struct BionicLocaleState; @@ -90,6 +90,7 @@ int mocktail_bionic_cxa_thread_atexit_impl( mocktail::compat::BionicThreadDestructor destructor, void* argument, void* dso_handle); void mocktail_bionic_arc4random_buf(void* buffer, size_t size); +int mocktail_bionic_atoi(const char* text); mocktail::compat::BionicMallinfoSnapshot mocktail_bionic_mallinfo(); int mocktail_bionic_sysinfo(struct sysinfo* info); int mocktail_bionic_uname(struct utsname* name); diff --git a/src/compat/bionic_host_libc_runtime.cc b/src/compat/bionic_host_libc_runtime.cc index 9ec8eff..d1d6cd6 100644 --- a/src/compat/bionic_host_libc_runtime.cc +++ b/src/compat/bionic_host_libc_runtime.cc @@ -323,8 +323,13 @@ int BionicStrError(int error_number, char* buffer, ::strerror_r(error_number, host_buffer.data(), host_buffer.size()); const char* message = HostStrErrorResult(host_result, host_buffer.data()); - std::array unknown_buffer{}; - if (message == nullptr) { + std::array unknown_buffer{}; + const char* unknown_message = HostStrErrorResult( + ::strerror_r(-1, unknown_buffer.data(), unknown_buffer.size()), + unknown_buffer.data()); + if (message == nullptr || + (error_number != 0 && unknown_message != nullptr && + std::strcmp(message, unknown_message) == 0)) { std::snprintf(unknown_buffer.data(), unknown_buffer.size(), "Unknown error %d", error_number); message = unknown_buffer.data(); @@ -373,6 +378,10 @@ extern "C" void mocktail_bionic_arc4random_buf(void* buffer, size_t size) { mocktail::compat::BionicArc4RandomBuffer(buffer, size); } +extern "C" int mocktail_bionic_atoi(const char* text) { + return static_cast(std::strtol(text, nullptr, 10)); +} + extern "C" mocktail::compat::BionicMallinfoSnapshot mocktail_bionic_mallinfo() { return mocktail::compat::BionicMallinfo(); } diff --git a/src/compat/bionic_pthread_create_runtime.cc b/src/compat/bionic_pthread_create_runtime.cc index e34fcf6..af5ff8e 100644 --- a/src/compat/bionic_pthread_create_runtime.cc +++ b/src/compat/bionic_pthread_create_runtime.cc @@ -114,7 +114,7 @@ int CopySupportedThreadAttributes(const MocktailBionicPthreadAttr& source, if (RejectRealtimeScheduling(source.sched_policy)) { return EPERM; } - if (source.sched_policy != SCHED_NORMAL) { + if (source.sched_policy != SCHED_OTHER) { result = pthread_attr_setschedpolicy(destination, source.sched_policy); if (result != 0) { return result; diff --git a/src/legacy/legacy_runtime.cc b/src/legacy/legacy_runtime.cc index 4f338cf..3a37c74 100644 --- a/src/legacy/legacy_runtime.cc +++ b/src/legacy/legacy_runtime.cc @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/src/linker/linker.cc b/src/linker/linker.cc index 24a8df1..e8461cb 100644 --- a/src/linker/linker.cc +++ b/src/linker/linker.cc @@ -134,7 +134,7 @@ bool IsBionicLibcOnlySymbol(std::string_view symbol) { } return symbol == "__cmsg_nxthdr" || symbol == "__cxa_thread_atexit_impl" || symbol == "__readlink_chk" || symbol == "__register_atfork" || - symbol == "arc4random_buf" || symbol == "geteuid" || + symbol == "arc4random_buf" || symbol == "atoi" || symbol == "geteuid" || symbol == "getuid" || symbol == "lseek64" || symbol == "mallinfo" || symbol == "pread64" || symbol == "pwrite64" || symbol == "sigaction" || symbol == "strerror_r" || @@ -384,6 +384,8 @@ void RegisterBionicHostLibcRuntimeForLibc() { RegisterSyntheticSymbol("libc.so", "arc4random_buf", reinterpret_cast( mocktail_bionic_arc4random_buf)); + RegisterSyntheticSymbol("libc.so", "atoi", + reinterpret_cast(mocktail_bionic_atoi)); RegisterSyntheticSymbol("libc.so", "mallinfo", reinterpret_cast(mocktail_bionic_mallinfo)); RegisterSyntheticSymbol("libc.so", "sysinfo", diff --git a/src/runtime/external_launch_broker.cc b/src/runtime/external_launch_broker.cc index 43e5206..750633d 100644 --- a/src/runtime/external_launch_broker.cc +++ b/src/runtime/external_launch_broker.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/src/update/readiness_canary.cc b/src/update/readiness_canary.cc index 358ea4b..cf33c3f 100644 --- a/src/update/readiness_canary.cc +++ b/src/update/readiness_canary.cc @@ -473,7 +473,9 @@ CanaryResult RunReadinessCanary(const CanaryOptions& options) { } std::filesystem::remove_all(isolated, filesystem_error); if (!result.error.empty()) return result; - result.exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : 128; + result.exit_code = WIFEXITED(status) + ? WEXITSTATUS(status) + : 128 + (WIFSIGNALED(status) ? WTERMSIG(status) : 0); if (result.exit_code != 0) { result.error = "graphics canary exited with status " + diff --git a/tests/bionic_host_libc_runtime_test.cc b/tests/bionic_host_libc_runtime_test.cc index 663bea7..2809cb0 100644 --- a/tests/bionic_host_libc_runtime_test.cc +++ b/tests/bionic_host_libc_runtime_test.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "libc_shim/libc_shim.h" @@ -205,6 +206,21 @@ TEST(BionicHostLibcRuntimeTest, HidesPrivilegedHostIdentityFromAndroidGuest) { mocktail::compat::NormalizeBionicApplicationUid(::geteuid())); } +TEST(BionicHostLibcRuntimeTest, ParsesAtoiWithBionicOverflowBehavior) { + EXPECT_EQ(mocktail_bionic_atoi(""), 0); + EXPECT_EQ(mocktail_bionic_atoi("invalid"), 0); + EXPECT_EQ(mocktail_bionic_atoi(" -42suffix"), -42); + EXPECT_EQ(mocktail_bionic_atoi("2147483647"), INT_MAX); + EXPECT_EQ(mocktail_bionic_atoi("-2147483648"), INT_MIN); + EXPECT_EQ(mocktail_bionic_atoi("2147483648"), INT_MIN); + EXPECT_EQ(mocktail_bionic_atoi("4294967295"), -1); + EXPECT_EQ(mocktail_bionic_atoi("9999999999"), 1410065407); + + errno = 0; + EXPECT_EQ(mocktail_bionic_atoi("9223372036854775808"), -1); + EXPECT_EQ(errno, ERANGE); +} + TEST(BionicHostLibcRuntimeTest, UsesBionicPosixStrErrorContract) { std::array buffer{}; @@ -214,9 +230,18 @@ TEST(BionicHostLibcRuntimeTest, UsesBionicPosixStrErrorContract) { EXPECT_NE(std::strstr(buffer.data(), "Invalid"), nullptr); EXPECT_EQ(errno, EDOM); - buffer.fill('\0'); - EXPECT_EQ(mocktail_bionic_strerror_r(4567, buffer.data(), buffer.size()), 0); - EXPECT_NE(std::strstr(buffer.data(), "4567"), nullptr); + EXPECT_EQ(mocktail_bionic_strerror_r(0, buffer.data(), buffer.size()), 0); + EXPECT_STREQ(buffer.data(), std::strerror(0)); + EXPECT_EQ(errno, EDOM); + + for (const int error_number : {-1, 4567, INT_MIN, INT_MAX}) { + errno = EDOM; + ASSERT_EQ(mocktail_bionic_strerror_r(error_number, buffer.data(), + buffer.size()), 0); + EXPECT_EQ(std::string(buffer.data()), + "Unknown error " + std::to_string(error_number)); + EXPECT_EQ(errno, EDOM); + } std::array truncated{}; errno = 0; diff --git a/tests/linker_registry_test.cc b/tests/linker_registry_test.cc index 860f75d..75816bd 100644 --- a/tests/linker_registry_test.cc +++ b/tests/linker_registry_test.cc @@ -130,6 +130,8 @@ TEST(LinkerRegistryTest, KeepsHostIndependentBionicAbiOwnedByLibc) { reinterpret_cast(mocktail___readlink_chk)); EXPECT_EQ(symbols.at("arc4random_buf"), reinterpret_cast(mocktail_bionic_arc4random_buf)); + EXPECT_EQ(symbols.at("atoi"), + reinterpret_cast(mocktail_bionic_atoi)); EXPECT_EQ(symbols.at("mallinfo"), reinterpret_cast(mocktail_bionic_mallinfo)); EXPECT_EQ(symbols.at("sysinfo"), diff --git a/tests/native_update_test.cc b/tests/native_update_test.cc index 19e37a3..a145c14 100644 --- a/tests/native_update_test.cc +++ b/tests/native_update_test.cc @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -272,6 +273,24 @@ TEST(ReadinessCanaryTest, PreservesEtc2DriverOverride) { } } +TEST(ReadinessCanaryTest, ReportsTerminatingSignal) { + TemporaryDirectory temporary; + CanaryOptions options; + options.runtime_binary = temporary.root() / "runtime"; + options.cache_root = temporary.root() / "cache"; + options.state_root = temporary.root() / "state"; + options.payload_directory = temporary.root() / "payload"; + options.timeout_seconds = 5; + Write(options.runtime_binary, "#!/bin/sh\nkill -TERM $$\n"); + ASSERT_EQ(chmod(options.runtime_binary.c_str(), 0700), 0); + + const auto result = RunReadinessCanary(options); + EXPECT_FALSE(result); + EXPECT_EQ(result.exit_code, 128 + SIGTERM); + EXPECT_EQ(result.error, "graphics canary exited with status " + + std::to_string(128 + SIGTERM)); +} + TEST(ReadinessCanaryTest, AcceptsRealPresentWithoutShaderPackSummary) { const std::string valid = "[compat] legacy binary patches: disabled\n" @@ -1751,6 +1770,7 @@ TEST(PayloadStoreTest, StagesAndPromotesVerifiedExactPayload) { temporary.root() / "compatibility.json"; Write(compatibility, "{\"schema_version\":1,\"profiles\":[{" + "\"abi\":\"" + std::string(compat::kGuestAbi) + "\"," "\"version_name\":\"2.727.1199\",\"version_code\":2628," "\"elf_build_id\":\"1686400865ae0e408cd7bd67de7a439625c6fd13\"," "\"status\":\"supported\",\"default_allowed\":true," diff --git a/third_party/mcpelauncher-linker/include/assert.h b/third_party/mcpelauncher-linker/include/assert.h index 7205cce..3ffb4a1 100644 --- a/third_party/mcpelauncher-linker/include/assert.h +++ b/third_party/mcpelauncher-linker/include/assert.h @@ -1,4 +1,5 @@ +#include #include "../bionic/libc/include/assert.h" #ifdef __BIONIC__ #undef __BIONIC__ -#endif \ No newline at end of file +#endif diff --git a/third_party/mcpelauncher-linker/include/compat.h b/third_party/mcpelauncher-linker/include/compat.h index 4f435e0..4ce7490 100644 --- a/third_party/mcpelauncher-linker/include/compat.h +++ b/third_party/mcpelauncher-linker/include/compat.h @@ -15,8 +15,12 @@ typedef std::atomic_int atomic_int; typedef std::atomic_uint atomic_uint; #endif +#ifndef PAGE_SIZE #define PAGE_SIZE 4096 +#endif +#ifndef PAGE_MASK #define PAGE_MASK (~(PAGE_SIZE - 1)) +#endif #if !defined(__APPLE__) && !defined(__FreeBSD__) #define DEF_WEAK(a) #define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1)) diff --git a/third_party/mcpelauncher-linker/include/sys/cdefs.h b/third_party/mcpelauncher-linker/include/sys/cdefs.h index 3e6455b..53749da 100644 --- a/third_party/mcpelauncher-linker/include/sys/cdefs.h +++ b/third_party/mcpelauncher-linker/include/sys/cdefs.h @@ -1,6 +1,12 @@ #pragma once #ifndef __APPLE__ +#pragma push_macro("_FORTIFY_SOURCE") +#pragma push_macro("__bos") +#undef _FORTIFY_SOURCE +#undef __bos #include "../../bionic/libc/include/sys/cdefs.h" +#pragma pop_macro("__bos") +#pragma pop_macro("_FORTIFY_SOURCE") #endif #if defined(__has_include_next) #if __has_include_next()