Created
May 22, 2026 12:53
-
-
Save MichaelWS/9e97f791db704f078dcf66d0dd9245ee to your computer and use it in GitHub Desktop.
fix crostini antigravity
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
| #!/usr/bin/env python3 | |
| """ | |
| VA39 patch for the Antigravity linux_arm64 binary on Chromebook/Crostini. | |
| Scans instruction patterns to patch TCMalloc for a 39-bit | |
| virtual address space instead of the default 48-bit, fixing | |
| the MmapAligned() crash. | |
| """ | |
| import hashlib | |
| import shutil | |
| import struct | |
| import sys | |
| from pathlib import Path | |
| # Adjust this path if the crash output specified a different $BINARY_PATH | |
| src = Path(sys.argv[1] if len(sys.argv) > 1 else "/usr/local/bin/agy") | |
| dst = Path(str(src) + ".va39") | |
| if not src.exists(): | |
| raise SystemExit(f"Input binary does not exist: {src}") | |
| print(f"Input binary : {src}") | |
| print(f"SHA256 in : {hashlib.sha256(src.read_bytes()).hexdigest()}\n") | |
| shutil.copyfile(src, dst) | |
| data = bytearray(dst.read_bytes()) | |
| def get(off): | |
| return struct.unpack_from("<I", data, off)[0] | |
| def put(off, word): | |
| struct.pack_into("<I", data, off, word) | |
| # 1. Find google_malloc section | |
| lo, hi = 0, len(data) | |
| if data[:4] == b"\x7fELF": | |
| e_shoff = struct.unpack_from("<Q", data, 40)[0] | |
| e_shentsize = struct.unpack_from("<H", data, 58)[0] | |
| e_shnum = struct.unpack_from("<H", data, 60)[0] | |
| e_shstrndx = struct.unpack_from("<H", data, 62)[0] | |
| shstr_base = e_shoff + e_shstrndx * e_shentsize | |
| shstr_off = struct.unpack_from("<Q", data, shstr_base + 24)[0] | |
| for i in range(e_shnum): | |
| base = e_shoff + i * e_shentsize | |
| sh_name = struct.unpack_from("<I", data, base)[0] | |
| sh_offset = struct.unpack_from("<Q", data, base + 24)[0] | |
| sh_size = struct.unpack_from("<Q", data, base + 32)[0] | |
| try: | |
| nend = data.index(b"\x00", shstr_off + sh_name) | |
| section = data[shstr_off + sh_name : nend].decode("utf-8") | |
| if section == "google_malloc": | |
| lo, hi = sh_offset, sh_offset + sh_size | |
| print(f"Found google_malloc section: 0x{lo:x} - 0x{hi:x}") | |
| break | |
| except ValueError: | |
| pass | |
| # 2. ubfx #42,#3 -> #35,#3 and lsl #42 -> #35 | |
| ubfx_count, lsl_count = 0, 0 | |
| for off in range(lo, hi, 4): | |
| w = get(off) | |
| if (w & 0x7F800000) == 0x53000000: | |
| immr, imms = (w >> 16) & 0x3F, (w >> 10) & 0x3F | |
| if immr == 42 and imms == 44: | |
| put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (35 << 16) | (37 << 10)) | |
| ubfx_count += 1 | |
| elif immr == 22 and imms == 21: | |
| put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (29 << 16) | (28 << 10)) | |
| lsl_count += 1 | |
| print(f"[1] ubfx patches : {ubfx_count}\n lsl patches : {lsl_count}") | |
| # 3. Random address mask pairs | |
| mask_count = 0 | |
| for off in range(lo, hi - 4, 4): | |
| if get(off) == 0x92D3800A and get(off + 4) == 0xF2E0000A: | |
| put(off, 0x9280000A) | |
| put(off + 4, 0xD35DFD4A) | |
| mask_count += 1 | |
| print(f"[2] Random mask : {mask_count}") | |
| # 4. MmapAlignedLocked upper bound | |
| mmap_count = 0 | |
| for off in range(lo, hi, 4): | |
| if get(off) == 0xF2E00029: | |
| put(off, 0xD3596129) | |
| mmap_count += 1 | |
| print(f"[3] MmapAligned : {mmap_count}") | |
| # 5. Inlined tag constants | |
| word_rewrites = { | |
| 0xD2C20009: 0xD2C00409, 0xD2C2000A: 0xD2C0040A, 0xF2C20008: 0xF2DFF408, | |
| 0xF2C20009: 0xF2DFF409, 0xD2C10009: 0xD2C00209, 0xD2C1000A: 0xD2C0020A, | |
| 0xF2C38008: 0xF2DFF708, 0xF2C38009: 0xF2DFF709, 0x92560A6C: 0x925D0A6C, | |
| 0x92560A6A: 0x925D0A6A, 0xD2C3000D: 0xD2C0060D, 0xD2C3000C: 0xD2C0060C, | |
| 0xD2C08008: 0xD2C00108, | |
| } | |
| counts = {old: 0 for old in word_rewrites} | |
| for off in range(lo, hi, 4): | |
| w = get(off) | |
| if w in word_rewrites: | |
| put(off, word_rewrites[w]) | |
| counts[w] += 1 | |
| print(f"[4] Tag constants: {sum(counts.values())} words rewritten") | |
| dst.write_bytes(data) | |
| dst.chmod(0o755) | |
| print(f"\nSHA256 out : {hashlib.sha256(dst.read_bytes()).hexdigest()}") | |
| print(f"Output : {dst}\n") | |
| if ubfx_count == 0 or mask_count == 0: | |
| print("WARNING: No patches applied - binary structure may have changed.") | |
| else: | |
| print("Patch looks complete. To replace original and test:") | |
| print(f" sudo mv {dst} {src}") | |
| print(f" {src} --version") |
MichaelWS
commented
Jul 9, 2026
via email
Author
i would hope so!
…On Thu, Jul 9, 2026, 12:12 Samuel ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
You sir, are a legend! This actually works!!
—
Reply to this email directly, view it on GitHub
<https://gist.github.com/MichaelWS/9e97f791db704f078dcf66d0dd9245ee#gistcomment-6242762>
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOJWAYKT6HMMMGWJRIUC7T5D7AALBFKMF2HI4TJMJ2XIZLTSOBKK5TBNR2WLJZRGMZTGOBVG6SG4YLNMWUGCY3UN5ZF62LEQKSXMYLMOVS2I5DSOVS2I3TBNVS3W5DIOJSWCZC7OBQXE5DJMNUXAYLOORPWCY3UNF3GS5DZQKSXMYLMOVS2IZ3JON2KI3TBNVS2W5DIOJSWCZC7OR4XAZNMON2WE2TFMN2F65DZOBS2WR3JON2EG33NNVSW45FGORXXA2LDOOIYFJDUPFYGLJDHNFZXJJLWMFWHKZNJGE2DQOJXG4ZTKMNHORZGSZ3HMVZKMY3SMVQXIZI>
.
You are receiving this email because you authored the thread.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment