- Replace x86_64 shellcode/ELF in shell_elf[] with aarch64 equivalent (e_machine=0xb7, MOVZ/SVC instructions, syscall numbers 144/146/159/221). - Update verify_byte() check at post-write to look for the aarch64 MOVZ opcode signature (0x80 0xd2) instead of the x86 (0x31 0xff). - Update su_marker[] to match the first 8 bytes of the aarch64 shellcode. Tested on Kali aarch64 6.19.11+kali-arm64; xfrm-ESP leg lands cleanly. rxrpc leg is x86-only (oopses on aarch64 in flush_dcache_page). |
||
|---|---|---|
| assets | ||
| exp.c | ||
| README.md | ||
Dirty Frag (aarch64 port)
Port of V4bel/dirtyfrag to 64-bit ARM (aarch64). The original vulnerability discovery, write-up, and exploit are by Hyunwoo Kim (@v4bel). This repository only adapts the embedded payload and verification logic so the exploit lands on aarch64 Linux.
Abstract
Dirty Frag chains two page-cache write vulnerabilities — xfrm-ESP Page-Cache Write (CVE-2026-43284) and RxRPC Page-Cache Write (CVE-2026-43500) — into a universal
local privilege escalation. The upstream PoC ships with an x86_64-only payload
(both the planted ELF and the verification logic). On aarch64 distributions the
underlying kernel bugs are still present and the xfrm-ESP primitive itself works
unmodified — only the userspace logic prematurely declares failure because it
checks for x86 byte signatures.
This port replaces:
- the 192-byte embedded x86_64 root-shell ELF with an aarch64 equivalent
(
e_machine = 0xb7,MOVZ/SVC #0shellcode, aarch64 syscall numberssetgid=144,setuid=146,setgroups=159,execve=221); - the post-write
verify_byte()check, which previously looked for the x86 prologue0x31 0xffat the entry offset — now checks for the aarch64MOVZopcode bytes0x80 0xd2at offsets0x7a/0x7b; - the
su_marker[]array used bysu_already_patched()— now holds the first eight bytes of the aarch64 shellcode (00 00 80 d2 08 12 80 d2).
These are the only three changes against upstream. The kernel-side primitive
(xfrm-ESP page-cache write via splice + vmsplice) is unchanged.
What works / what doesn't on aarch64
| Leg | x86_64 | aarch64 | Notes |
|---|---|---|---|
xfrm-ESP page-cache write |
works | works | Uses real struct page* via splice from the target file. Cache-coherency differences do not affect the write path. |
RxRPC page-cache write |
works | kernel oops | Supplies a fabricated struct page* that x86 flush_dcache_page() ignores (no-op) but aarch64 dereferences (real cache flush) → translation fault. |
Because the xfrm-ESP leg succeeds on aarch64, the rxrpc fallback is unnecessary and the exploit obtains a root shell through the same flow as upstream.
If you only have access to a distribution that blocks unprivileged user-namespace creation (e.g., Ubuntu under AppArmor), the xfrm-ESP leg will not run. On those systems the rxrpc fallback is currently not portable to aarch64 — see Limitations below.
Exploiting
git clone https://github.com/<your-user>/dirtyfrag-aarch64.git && \
cd dirtyfrag-aarch64 && \
gcc -O0 -Wall -o exp exp.c -lutil && \
./exp
Pass -v or set DIRTYFRAG_VERBOSE=1 to see the patching progress.
This PoC is for authorized testing only. Do not run it on systems you do not own or are not contracted to test.
Cleanup
After running the exploit, the page cache for /usr/bin/su is polluted. Either
drop the caches or reboot:
echo 3 | sudo tee /proc/sys/vm/drop_caches
The on-disk binary is not modified — only the in-memory page cache is.
Tested
- Kali ARM (Apple Silicon, VMware Fusion), kernel
6.19.11+kali-arm64, glibc built foraarch64-linux-gnu. Both modulesesp4andxfrm_userautoload cleanly on first use; unprivileged user namespaces are enabled by default.
If you test this on additional aarch64 distributions (Raspberry Pi OS, Ubuntu Server for ARM, openSUSE aarch64, Fedora aarch64, Amazon Linux 2023 aarch64, Oracle Linux ARM, etc.) please open an issue or PR with the kernel version and result.
Affected versions
Same scope as upstream — these are kernel bugs, not architecture-specific:
- CVE-2026-43284 (xfrm-ESP):
cac2661c53f3(2017-01-17) →f4c50a4034e6(2026-05-05) - CVE-2026-43500 (RxRPC):
2dc334f1a63a(2023-06-08) →aa54b1d27fe0(2026-05-10)
Kernels built before those fix commits are vulnerable. As of this port's publication the patches are in mainline but have not yet been backported to every aarch64 distribution.
Mitigation
Same as upstream:
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' \
> /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; \
echo 3 > /proc/sys/vm/drop_caches; true"
Update to a kernel that includes both fix commits as soon as your distribution ships the backport.
Limitations
- rxrpc fallback is not ported. On aarch64 the rxrpc primitive faults the
kernel in
flush_dcache_pagebecause of how the bug constructs a fakestruct page*. Making that leg work would require a different page-supply technique (real backing page that aliases the target file's page cache), which is a research problem, not a code change. - Only
/usr/bin/suis patched. The/etc/passwdbackdoor path used by the rxrpc leg is unavailable on aarch64 for the reason above. If your target distribution restricts unprivileged userns and you cannot use the xfrm-ESP leg either, this port will not give you root.
Credit
- Original vulnerability discovery, write-up, and exploit: Hyunwoo Kim (@v4bel) — see upstream repo V4bel/dirtyfrag and the technical write-up linked from there.
- aarch64 port (this repo): payload + verification adapted to aarch64 only; all kernel-exploitation logic is upstream's.
License
The upstream repository does not ship an explicit license file. This fork preserves attribution and is published for security-research purposes only. If the upstream author requests removal or relicensing, please open an issue and the repository will be updated accordingly.