
Prova di concetto di un exploit di escalation dei privilegi locali per una race condition nella rate-table della qdisc di Linux, che utilizza il grooming dell'heap BPF e un leak tramite pipe per ottenere i privilegi di root.

Questo repository contiene un proof-of-concept di elevazione dei privilegi locali per CVE-2026-68138, una race condition nel codice delle rate-table del traffic-control di Linux. Nell'ambiente QEMU testato, il PoC eleva i privilegi da un processo ordinario con UID esterno 1000 a una shell con UID 0 nel namespace utente iniziale.
Avvertenza
Questo codice corrompe intenzionalmente lo stato dell'heap del kernel. Usalo solo in una VM isolata e monouso di tua proprietà. Una race mancata o una pulizia prematura può causare il panic del guest. Non eseguirlo su workstation, server o sistemi di terze parti.
qdisc_get_rtab() e qdisc_put_rtab() gestiscono una lista concatenata singolarmente globale al processo, qdisc_rtab_list, e un semplice int refcnt non atomico. Storicamente, i chiamanti detenevano il mutex RTNL, che serializzava l'accesso alla lista e al contatore di riferimento.
Il classificatore flower imposta TCF_PROTO_OPS_DOIT_UNLOCKED. Una richiesta RTM_NEWTFILTER per una regola flower può quindi raggiungere un'azione police e chiamare gli helper delle rate-table qdisc senza RTNL:
tc_new_tfilter()
-> fl_change()
-> tcf_exts_validate_ex()
-> tcf_action_init()
-> tcf_police_init()
-> qdisc_get_rtab()/qdisc_put_rtab()
Richieste concorrenti che usano la stessa rate table possono entrare in race sulla lista globale e sul suo contatore di riferimento. Il risultato è un use-after-free o double-free di struct qdisc_rate_table, un oggetto di 1056 byte allocato da kmalloc-2k sul kernel x86-64 testato.
Poiché la lista è globale e non per-network-namespace, le richieste provenienti da namespace di rete separati fanno comunque race sullo stesso oggetto.
Il record CNA di Linux identifica il commit di introduzione 470502de5bdb, rilasciato in Linux 5.1.
| Serie | Stato | Commit/versione |
|---|---|---|
| Linux precedente alla 5.1 | Non interessato | La modifica introduttiva è assente |
| Linux dalla 5.1 alla 7.1.5 | Interessato salvo presenza di un backport del fornitore | da 470502de5bdb fino al commit precedente la correzione stabile |
| Linux 7.1.y | Corretto | 7.1.6, fb29e1b41052 |
| Serie di sviluppo di Linux 7.2 | Interessato prima della rc5 | dalla rc1 alla rc4 |
| Mainline | Corretto | 7.2-rc5, f43ee0c0730d |
I kernel delle distribuzioni spesso applicano backport delle correzioni senza portarsi alla versione upstream mostrata sopra. Verifica se uno dei due commit di correzione, o la modifica equivalente allo spinlock delle rate-table qdisc, sia presente nel codice sorgente esatto del kernel usato dal sistema.
L'exploit è stato sviluppato e validato contro il commit vulnerabile 92d3817649df2b0b6a008a686c8275c88d7ef594, padre diretto della correzione mainline. Il controllo su kernel corretto ha usato f43ee0c0730d6191629b5ee1ceae27b1ebfdc047.
Alla data del 2026-08-12, la ricerca nel tracker CVE di Ubuntu non restituiva alcuna voce per questa CVE. La tabella seguente è quindi un'ispezione diretta del sorgente, non una determinazione dello stato di sicurezza di Canonical. Ogni tag Ubuntu collegato ha ancora la qdisc_rtab_list senza lock e non presenta la qdisc_rtab_lock correttiva.
| Linea Ubuntu | Pacchetto/tag ispezionato | Esito dell'ispezione del sorgente |
|---|---|---|
| Ubuntu 22.04 GA | 5.15.0-187.197 | Codice vulnerabile presente; exploit completo riprodotto in QEMU |
| Ubuntu 22.04 HWE | 6.8.0-136.136~22.04.1 | Codice vulnerabile presente; catena di exploit non testata |
| Ubuntu 24.04 HWE | 7.0.0-28.28~24.04.1 | Codice vulnerabile presente; questa catena di exploit non è compatibile con il suo hardening dell'allocatore |
| Ubuntu 26.04 | 7.0.0-28.28 | Codice vulnerabile presente; questa catena di exploit non è compatibile con il suo hardening dell'allocatore |
Nessun pacchetto Ubuntu corretto è stato identificato a quella data di ispezione. I futuri pacchetti Ubuntu dovrebbero essere verificati per un backport equivalente alle correzioni upstream collegate, piuttosto che giudicati solo dal numero di versione.
L'exploit specifico per la build Ubuntu 22.04, il laboratorio QEMU, il checksum esatto dell'immagine e le condizioni sono documentati in ubuntu/README.md. È stato validato contro il kernel ufficiale 5.15.0-187-generic #197-Ubuntu con il memory-cgroup accounting abilitato.
Il bug sottostante e questa particolare catena di exploit hanno requisiti diversi. Il PoC è stato validato con:
CONFIG_USER_NS=y e CONFIG_NET_NS=y;CONFIG_NET_CLS=y, CONFIG_NET_CLS_FLOWER=y, CONFIG_NET_CLS_ACT=y e CONFIG_NET_ACT_POLICE=y;CONFIG_TMPFS_XATTR=y per l'heap spray simple_xattr;CONFIG_MODULES=y e un /sbin/modprobe utilizzabile per l'helper root finale;CONFIG_MEMCG=n, così le allocazioni qdisc/BPF/pipe/xattr usate da questa catena condividono la cache kmalloc-2k prevista;CONFIG_SLAB_BUCKETS=y, la randomizzazione della freelist e l'hardening della freelist erano abilitati nel kernel di test riuscito. Il KASLR non viene aggirato intrinsecamente con un indirizzo hard-coded: il PoC ottiene i puntatori necessari alla pagina e alle operazioni dalla pipe leak. Il laboratorio fornito usava nokaslr per semplificare il debug.
I kernel con memory-cgroup accounting abilitato o con layout di allocatore/cache diversi richiedono una strategia di reclaim differente. Il PoC rifiuta deliberatamente di dichiarare portabilità attraverso configurazioni di distribuzione arbitrarie.
La variante Ubuntu separata implementa quella diversa strategia di reclaim; i suoi requisiti sono intenzionalmente più ristretti e sono elencati in ubuntu/README.md.
Quattro thread worker entrano in namespace di rete distinti e creano filtri flower con azioni police. Tre worker seguono il percorso di azione riuscito; uno fornisce deliberatamente uno stimatore non valido dopo aver acquisito entrambi i riferimenti alla rate table, forzando il percorso di pulizia. Questa combinazione rende riproducibile la manipolazione concorrente del contatore di riferimento e della lista senza condividere lo stato del classificatore flower tra i worker.
qdisc_rate_table con BPF classico