Conversation
…c file In after_openat(), compat_copy_to_user previously passed sizeof(ORIGIN_RC_FILES[args->local.data3 - 1]) as the copy length. Because ORIGIN_RC_FILES is declared as const char [][64], the sizeof evaluated to 64 bytes (0x40) rather than the actual string length. When userspace (/system/bin/init) opens /system/etc/init/hw/init.rc (28 bytes with null terminator), LLVM libc++ allocates a heap buffer of ~32 bytes. Copying 64 bytes back into userspace caused a 32-byte heap buffer overflow, corrupting adjacent Scudo allocator chunk headers and triggering an immediate SIGSEGV during init::Parser::ParseData() on Android 14. Fix this by: 1. Copying strlen(origin_rc) + 1 bytes in after_openat() to restore only the exact string bounds without overflowing userspace memory. 2. In before_openat(), checking strlen(origin_rc) + 1 >= sizeof(REPLACE_RC_FILE) before attempting an in-place compat_copy_to_user, safely falling back to copy_to_user_stack() for shorter paths like /init.rc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix out-of-bounds heap write in
openathook caused by using arraysizeofinstead of string length, which corrupted Scudo chunk headers in Android 14init.Problem
In
after_openat(),compat_copy_to_userpassedsizeof(ORIGIN_RC_FILES[args->local.data3 - 1])as the copy length. BecauseORIGIN_RC_FILESis declared asconst char [][64],sizeofevaluates to 64 bytes (0x40) rather than the actual string length.When userspace (
/system/bin/init) opens/system/etc/init/hw/init.rc(28 bytes with null terminator), LLVMlibc++allocates a heap buffer of ~32 bytes (as it exceeds the 23-byte SSO limit). Copying 64 bytes back into userspace causes an out-of-bounds 32-byte heap write into adjacent memory, corrupting Scudo allocator chunk headers and triggering an immediateSIGSEGVduringinit::Parser::ParseData()on Android 14.Solution
after_openat(): Copystrlen(origin_rc) + 1bytes instead ofsizeof(ORIGIN_RC_FILES[...]).before_openat(): Verifystrlen(origin_rc) + 1 >= sizeof(REPLACE_RC_FILE)before attempting an in-placecompat_copy_to_user, safely falling back tocopy_to_user_stack()for shorter targets like/init.rc(9 bytes).How Has This Been Tested?
/system/bin/initsuccessfully parses/system/etc/init/hw/init.rcwithout Scudo crashes./init.rc) fall back to stack copy without overflow.