
Une implémentation Go de PinTheft (CVE-2026-43494)
Portage Go de pintheft — LPE double-free RDS zcopy. Membre de la classe de vulnérabilités Dirty Frag.
[!IMPORTANT] Arch Linux est l'une des distributions les plus exposées à cette vulnérabilité, car elle fait partie des rares où le module RDS peut généralement être chargé par défaut.
Le bug se trouve dans rds_message_zcopy_from_user(). La fonction épingle les pages utilisateur une à une via FOLL_GET (GUP). Si une page ultérieure génère un défaut (par ex. une page de garde PROT_NONE), le chemin d'erreur appelle put_page() sur les pages déjà épinglées, puis rds_message_purge() appelle à nouveau __free_page() sur celles-ci car op_mmp_znotifier a été mis à NULL mais op_nents/les entrées sg ont été laissées intactes. Lorsque la page possède encore d'autres références, __free_page décrémente silencieusement le refcount. Chaque sendmsg qui échoue vole exactement une référence sur la première page.
CONFIG_INIT_ON_ALLOC_DEFAULT_ONÉpinglez la page cible via io_uring REGISTER_BUFFERS, ce qui ajoute GUP_PIN_COUNTING_BIAS (1024) au refcount via FOLL_PIN. Volez les 1024 références pin avec des envois zcopy en échec. Le refcount de la page est maintenant d'environ 1 (juste le mapping PTE). munmap emprunte le chemin normal __folio_put, qui appelle mem_cgroup_uncharge (en effaçant memcg_data) avant la libération. Aucun contrôle bad_page ne se déclenche.
io_uring conserve le struct page* brut dans son tableau bvec sans aucun contrôle de vivacité. Une fois la page récupérée comme page cache pour un binaire suid, IORING_OP_READ_FIXED y écrit notre charge utile via ce pointeur pendant.
IORING_REGISTER_CLONE_BUFFERS incrémente imu->refs. Un processus fils daemonisé issu d'un fork conserve le fd du ring clone ouvert — io_buffer_unmap voit refs > 1 et saute unpin_user_folio, empêchant ainsi la corruption du refcount sur la page libérée.
Épinglez sur le CPU 0, videz les entrées PCP obsolètes avant la libération — notre page atterrit en haut de pile lorsque l'allocateur de page cache la récupère.
REGISTER_BUFFERS(+1024) -> CLONE_BUFFERS(imu->refs=2) ->
daemon holds clone -> steal 1024 refs -> evict page cache ->
drain PCP -> munmap(free) -> pread(reclaim) ->
READ_FIXED(overwrite) -> verify -> exec -> root
go build -o pintheft-go .
./pintheft-go
En cas de succès, ouvre un shell root via PTY. Le binaire sur disque n'est pas modifié.
sudo cp /tmp/.backup_pintheft_<pid> /usr/bin/su && sudo chmod u+s /usr/bin/su
CONFIG_RDS=m, CONFIG_RDS_TCP=m (chargés automatiquement via SO_RDS_TRANSPORT=2)CONFIG_IO_URING=y avec io_uring_disabled=0btw j'adore Arch Linux :)