{"slug": "fix-crostini-antigravity", "title": "fix crostini antigravity", "summary": "This article provides a Python script that patches the \"Antigravity\" Linux ARM64 binary for use in Chrome OS's Crostini environment. The patch modifies TCMalloc memory allocation parameters to use a 39-bit virtual address space instead of the default 48-bit, which fixes an `MmapAligned()` crash. The script works by scanning for specific instruction patterns in the binary's `google_malloc` section and rewriting them to adjust address masks and bounds.", "body_md": "patch_va39\n\n      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.\n      \nLearn more about bidirectional Unicode characters\n\n \n    Show hidden characters\n\n#!/usr/bin/env python3\n\n\"\"\"\n\nVA39 patch for the Antigravity linux_arm64 binary on Chromebook/Crostini.\n\nScans instruction patterns to patch TCMalloc for a 39-bit\n\nvirtual address space instead of the default 48-bit, fixing \n\nthe MmapAligned() crash.\n\n\"\"\"\n\nimport\n \nhashlib\n\nimport\n \nshutil\n\nimport\n \nstruct\n\nimport\n \nsys\n\nfrom\n \npathlib\n \nimport\n \nPath\n\n# Adjust this path if the crash output specified a different $BINARY_PATH\n\nsrc\n \n=\n \nPath\n(\nsys\n.\nargv\n[\n1\n] \nif\n \nlen\n(\nsys\n.\nargv\n) \n>\n \n1\n \nelse\n \n\"/usr/local/bin/agy\"\n)\n\ndst\n \n=\n \nPath\n(\nstr\n(\nsrc\n) \n+\n \n\".va39\"\n)\n\nif\n \nnot\n \nsrc\n.\nexists\n():\n\n \nraise\n \nSystemExit\n(\nf\"Input binary does not exist: \n{\nsrc\n}\n\"\n)\n\nprint\n(\nf\"Input binary : \n{\nsrc\n}\n\"\n)\n\nprint\n(\nf\"SHA256 in    : \n{\nhashlib\n.\nsha256\n(\nsrc\n.\nread_bytes\n()).\nhexdigest\n()\n}\n\\n\n\"\n)\n\nshutil\n.\ncopyfile\n(\nsrc\n, \ndst\n)\n\ndata\n \n=\n \nbytearray\n(\ndst\n.\nread_bytes\n())\n\ndef\n \nget\n(\noff\n):\n\n \nreturn\n \nstruct\n.\nunpack_from\n(\n\"<I\"\n, \ndata\n, \noff\n)[\n0\n]\n\ndef\n \nput\n(\noff\n, \nword\n):\n\n \nstruct\n.\npack_into\n(\n\"<I\"\n, \ndata\n, \noff\n, \nword\n)\n\n# 1. Find google_malloc section\n\nlo\n, \nhi\n \n=\n \n0\n, \nlen\n(\ndata\n)\n\nif\n \ndata\n[:\n4\n] \n==\n \nb\"\n\\x7f\nELF\"\n:\n\n \ne_shoff\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<Q\"\n, \ndata\n, \n40\n)[\n0\n]\n\n \ne_shentsize\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<H\"\n, \ndata\n, \n58\n)[\n0\n]\n\n \ne_shnum\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<H\"\n, \ndata\n, \n60\n)[\n0\n]\n\n \ne_shstrndx\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<H\"\n, \ndata\n, \n62\n)[\n0\n]\n\n \nshstr_base\n \n=\n \ne_shoff\n \n+\n \ne_shstrndx\n \n*\n \ne_shentsize\n\n \nshstr_off\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<Q\"\n, \ndata\n, \nshstr_base\n \n+\n \n24\n)[\n0\n]\n\n \nfor\n \ni\n \nin\n \nrange\n(\ne_shnum\n):\n\n \nbase\n \n=\n \ne_shoff\n \n+\n \ni\n \n*\n \ne_shentsize\n\n \nsh_name\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<I\"\n, \ndata\n, \nbase\n)[\n0\n]\n\n \nsh_offset\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<Q\"\n, \ndata\n, \nbase\n \n+\n \n24\n)[\n0\n]\n\n \nsh_size\n \n=\n \nstruct\n.\nunpack_from\n(\n\"<Q\"\n, \ndata\n, \nbase\n \n+\n \n32\n)[\n0\n]\n\n \ntry\n:\n\n \nnend\n \n=\n \ndata\n.\nindex\n(\nb\"\n\\x00\n\"\n, \nshstr_off\n \n+\n \nsh_name\n)\n\n \nsection\n \n=\n \ndata\n[\nshstr_off\n \n+\n \nsh_name\n : \nnend\n].\ndecode\n(\n\"utf-8\"\n)\n\n \nif\n \nsection\n \n==\n \n\"google_malloc\"\n:\n\n \nlo\n, \nhi\n \n=\n \nsh_offset\n, \nsh_offset\n \n+\n \nsh_size\n\n \nprint\n(\nf\"Found google_malloc section: 0x\n{\nlo\n:x\n}\n - 0x\n{\nhi\n:x\n}\n\"\n)\n\n \nbreak\n\n \nexcept\n \nValueError\n:\n\n \npass\n\n# 2. ubfx #42,#3 -> #35,#3 and lsl #42 -> #35\n\nubfx_count\n, \nlsl_count\n \n=\n \n0\n, \n0\n\nfor\n \noff\n \nin\n \nrange\n(\nlo\n, \nhi\n, \n4\n):\n\n \nw\n \n=\n \nget\n(\noff\n)\n\n \nif\n (\nw\n \n&\n \n0x7F800000\n) \n==\n \n0x53000000\n:\n\n \nimmr\n, \nimms\n \n=\n (\nw\n \n>>\n \n16\n) \n&\n \n0x3F\n, (\nw\n \n>>\n \n10\n) \n&\n \n0x3F\n\n \nif\n \nimmr\n \n==\n \n42\n \nand\n \nimms\n \n==\n \n44\n:\n\n \nput\n(\noff\n, (\nw\n \n&\n \n~\n((\n0x3F\n \n<<\n \n16\n) \n|\n (\n0x3F\n \n<<\n \n10\n))) \n|\n (\n35\n \n<<\n \n16\n) \n|\n (\n37\n \n<<\n \n10\n))\n\n \nubfx_count\n \n+=\n \n1\n\n \nelif\n \nimmr\n \n==\n \n22\n \nand\n \nimms\n \n==\n \n21\n:\n\n \nput\n(\noff\n, (\nw\n \n&\n \n~\n((\n0x3F\n \n<<\n \n16\n) \n|\n (\n0x3F\n \n<<\n \n10\n))) \n|\n (\n29\n \n<<\n \n16\n) \n|\n (\n28\n \n<<\n \n10\n))\n\n \nlsl_count\n \n+=\n \n1\n\nprint\n(\nf\"[1] ubfx patches : \n{\nubfx_count\n}\n\\n\n    lsl patches  : \n{\nlsl_count\n}\n\"\n)\n\n# 3. Random address mask pairs\n\nmask_count\n \n=\n \n0\n\nfor\n \noff\n \nin\n \nrange\n(\nlo\n, \nhi\n \n-\n \n4\n, \n4\n):\n\n \nif\n \nget\n(\noff\n) \n==\n \n0x92D3800A\n \nand\n \nget\n(\noff\n \n+\n \n4\n) \n==\n \n0xF2E0000A\n:\n\n \nput\n(\noff\n, \n0x9280000A\n)\n\n \nput\n(\noff\n \n+\n \n4\n, \n0xD35DFD4A\n)\n\n \nmask_count\n \n+=\n \n1\n\nprint\n(\nf\"[2] Random mask  : \n{\nmask_count\n}\n\"\n)\n\n# 4. MmapAlignedLocked upper bound\n\nmmap_count\n \n=\n \n0\n\nfor\n \noff\n \nin\n \nrange\n(\nlo\n, \nhi\n, \n4\n):\n\n \nif\n \nget\n(\noff\n) \n==\n \n0xF2E00029\n:\n\n \nput\n(\noff\n, \n0xD3596129\n)\n\n \nmmap_count\n \n+=\n \n1\n\nprint\n(\nf\"[3] MmapAligned  : \n{\nmmap_count\n}\n\"\n)\n\n# 5. Inlined tag constants\n\nword_rewrites\n \n=\n {\n\n \n0xD2C20009\n: \n0xD2C00409\n, \n0xD2C2000A\n: \n0xD2C0040A\n, \n0xF2C20008\n: \n0xF2DFF408\n,\n\n \n0xF2C20009\n: \n0xF2DFF409\n, \n0xD2C10009\n: \n0xD2C00209\n, \n0xD2C1000A\n: \n0xD2C0020A\n,\n\n \n0xF2C38008\n: \n0xF2DFF708\n, \n0xF2C38009\n: \n0xF2DFF709\n, \n0x92560A6C\n: \n0x925D0A6C\n,\n\n \n0x92560A6A\n: \n0x925D0A6A\n, \n0xD2C3000D\n: \n0xD2C0060D\n, \n0xD2C3000C\n: \n0xD2C0060C\n,\n\n \n0xD2C08008\n: \n0xD2C00108\n,\n\n}\n\ncounts\n \n=\n {\nold\n: \n0\n \nfor\n \nold\n \nin\n \nword_rewrites\n}\n\nfor\n \noff\n \nin\n \nrange\n(\nlo\n, \nhi\n, \n4\n):\n\n \nw\n \n=\n \nget\n(\noff\n)\n\n \nif\n \nw\n \nin\n \nword_rewrites\n:\n\n \nput\n(\noff\n, \nword_rewrites\n[\nw\n])\n\n \ncounts\n[\nw\n] \n+=\n \n1\n\nprint\n(\nf\"[4] Tag constants: \n{\nsum\n(\ncounts\n.\nvalues\n())\n}\n words rewritten\"\n)\n\ndst\n.\nwrite_bytes\n(\ndata\n)\n\ndst\n.\nchmod\n(\n0o755\n)\n\nprint\n(\nf\"\n\\n\nSHA256 out   : \n{\nhashlib\n.\nsha256\n(\ndst\n.\nread_bytes\n()).\nhexdigest\n()\n}\n\"\n)\n\nprint\n(\nf\"Output       : \n{\ndst\n}\n\\n\n\"\n)\n\nif\n \nubfx_count\n \n==\n \n0\n \nor\n \nmask_count\n \n==\n \n0\n:\n\n \nprint\n(\n\"WARNING: No patches applied - binary structure may have changed.\"\n)\n\nelse\n:\n\n \nprint\n(\n\"Patch looks complete. To replace original and test:\"\n)\n\n \nprint\n(\nf\"  sudo mv \n{\ndst\n}\n \n{\nsrc\n}\n\"\n)\n\n \nprint\n(\nf\"  \n{\nsrc\n}\n --version\"\n)", "url": "https://wpnews.pro/news/fix-crostini-antigravity", "canonical_source": "https://gist.github.com/MichaelWS/9e97f791db704f078dcf66d0dd9245ee", "published_at": "2026-05-22 12:53:34+00:00", "updated_at": "2026-05-22 16:42:09.378654+00:00", "lang": "en", "topics": ["developer-tools", "open-source", "research"], "entities": ["Chromebook", "Crostini", "TCMalloc", "Antigravity", "VA39"], "alternates": {"html": "https://wpnews.pro/news/fix-crostini-antigravity", "markdown": "https://wpnews.pro/news/fix-crostini-antigravity.md", "text": "https://wpnews.pro/news/fix-crostini-antigravity.txt", "jsonld": "https://wpnews.pro/news/fix-crostini-antigravity.jsonld"}}