
Proof-of-concept che dimostra una fuga di dati microarchitetturale nei processori Loongson LA464/LA664 tramite i bit superiori indefiniti dei registri vettoriali LASX, simile a ZenBleed.
LoongBleed è una vulnerabilità hardware, concettualmente simile a ZenBleed (CVE-2023-20593) — che colpisce i processori Loongson LA464/LA664 che implementano sia LSX (SIMD a 128 bit) sia LASX (SIMD a 256 bit).
Su LoongArch, i registri LSX $vr (128 bit) sono alias della metà inferiore dei registri
LASX $xr (256 bit). Le istruzioni LSX e le operazioni in virgola mobile di base
sono definite per operare solo sui 128 bit inferiori (o su un loro sottoinsieme); i
bit superiori del corrispondente registro $xr sono indefiniti. Tuttavia, a causa
di un difetto microarchitetturale, queste operazioni possono far trapelare dati attraverso
i 128 bit superiori di $xr, esponendo dati sensibili attraverso confini di privilegio o
tra sibling SMT.
Nota sulla scoperta indipendente — Lo stesso difetto hardware sottostante è stato scoperto e pubblicato in modo indipendente dai ricercatori del CISPA Helmholtz Center for Information Security come LoongLeak (https://loongleakattack.com/), presentato a USENIX Security 2026 come "LoongLeak: Architectural Cross-Privilege-Boundary Data Leakage on LoongArch CPUs". Il nostro lavoro è stato sviluppato indipendentemente dal team LoongLeak; entrambi i gruppi sono giunti alla stessa conclusione che i processori Loongson LA464/LA664 fanno trapelare dati attraverso i bit superiori indefiniti dei registri LASX
$xr. Si noti che le istruzioni che utilizziamo per innescare la fuga non sono identiche a quelle riportate nel paper LoongLeak: il nostro PoC si basa su un diverso insieme di gadget (vor.v,vld,fld.d,fld.s) per riprodurre lo stesso difetto hardware sottostante. Inoltre, poiché la fuga può essere innescata da pure istruzioni registro-registro comevor.v(nessun caricamento in memoria coinvolto), la nostra analisi suggerisce che la causa principale sia probabilmente il riutilizzo di registri fisici: i bit superiori di un registro fisico riutilizzato non vengono cancellati, facendo trapelare dati obsoleti da un precedente occupante del registro. Questo differisce dall'analisi del paper LoongLeak, che attribuisce i dati trapelati alla cache dati L1.
Il proof-of-concept funziona come segue:
$xrN tramite xvld.xvst.Il PoC esegue ripetutamente questo gadget su 16 registri vettoriali architetturali
($xr0–$xr15) su thread vincolati a core fisici. I valori non nulli che
compaiono dopo l'istruzione indicano che la microarchitettura ha propagato dati
obsoleti o provenienti da un contesto diverso nello stato architetturale dei registri.
Il PoC supporta più istruzioni di test, selezionabili tramite --gadget:
Su LA664, tutti e quattro i gadget espongono la fuga, facendo trapelare al massimo 192 bit per
vettore. Su LA464, vld, fld.d e fld.s fanno trapelare (al massimo 224 bit per
vettore); il gadget predefinito vor.v non fa trapelare su LA464.
Usage: ./loongbleed_poc [OPTIONS]
Options:
-a, --all Launch one thread pinned to each physical core.
By default only thread on CPU 0 is launched.
-g, --gadget [vor|vld|fld.d|fld.s]
Use different instructions for testing.
-h, --help Show this help and exit.
# Single-thread mode on CPU 0
./run.sh
# Single-thread mode with vld gadget (required for LA464)
./run.sh --gadget vld
# All physical cores, default gadget
./run.sh -a
# All cores with fld.d gadget
./run.sh --all --gadget fld.d
Un thread vittima elabora dati sensibili su una CPU logica mentre il PoC sonda i registri sul suo sibling SMT. Il thread che spia può osservare frammenti dei dati della vittima nei bit superiori trapelati.
# Terminal 1 — start LoongBleed on CPU 0
./run.sh
# Terminal 2 — victim workload on the SMT sibling (CPU 1)
while true; do numactl -C 1 sort < /etc/shadow > /dev/null; done
Per una configurazione automatizzata, utilizzare lo script fornito:
./poc_la664.sh
Questo avvia un carico di lavoro sort sulla CPU 1 (il sibling SMT della CPU 0) e lancia
LoongBleed sulla CPU 0 con il gadget predefinito.
Un thread vittima elabora dati sensibili su una CPU mentre il PoC sonda
i registri sullo stesso core. Richiede --gadget vld poiché il gadget predefinito vor.v
non fa trapelare su LA464.
# Terminal 1 — start LoongBleed on CPU 0
./run.sh --gadget vld
# Terminal 2 — victim workload on the same core
while true; do numactl -C 0 sort < /etc/shadow > /dev/null; done
Per una configurazione automatizzata:
./poc_la464.sh
Questo avvia un carico di lavoro sort sulla CPU 0 e lancia LoongBleed con --gadget vld.
Il PoC è un programma C++ in un singolo file senza dipendenze esterne.
g++ -std=c++11 -O2 -march=native -pthread -o loongbleed_poc loongbleed_poc.cpp
Oppure utilizzare lo script fornito:
./run.sh
# or, on LA464:
./run.sh --gadget vld
Quando viene rilevata una fuga e i byte trapelati contengono una sequenza di almeno 8 caratteri ASCII stampabili contigui (0x20–0x7e), il PoC stampa:
[cpu 0] LEAK chunk=14 data=0x7461646e756f4620_6572617774666f53_0000000000000000_0000000000000000 ascii=............Software Foundat
$xr0–$xr15) ha innescato$xrN dopo
l'istruzione, visualizzato come data3_data2_data1_data0 dove:
data0 = bit [63:0] (i 64 bit più bassi del risultato)data1 = bit [127:64] (i 64 bit superiori della metà inferiore a 128 bit)data2 = bit [191:128] (i 64 bit inferiori della metà superiore a 128 bit)data3 = bit [255:192] (i 64 bit superiori della metà superiore a 128 bit)..Qualsiasi valore non nullo nei 128 bit superiori (data2 o data3) indica una
fuga di dati microarchitetturale.
La vulnerabilità è stata scoperta durante la lettura dell'articolo di Chips and Cheese "Loongson's LSX and LASX Vector Extensions". L'articolo notava che le istruzioni vettoriali possono lasciare dietro di sé alcuni residui di dati casuali. Questo ci ha portato a ipotizzare che il register renaming potrebbe non cancellare i registri — un meccanismo simile a ZenBleed — il che in teoria permetterebbe di far trapelare dati dello spazio kernel. Abbiamo quindi eseguito esperimenti per verificare questa ipotesi; la fuga si verifica effettivamente e si riproduce sia sul Loongson 3A5000 che sul 3A6000.
Questo progetto è fornito solo a scopo didattico e di ricerca sulla sicurezza.
| Gadget | Istruzione | Descrizione | Fuga su LA664 | Fuga su LA464 |
|---|
vor | vor.v $vrN, $vrN, $vrN | OR bit a bit di $vrN con se stesso | Sì | No |
vld | vld $vrN, … | Caricamento a 128 bit dalla memoria in $vrN | Sì | Sì |
fld.d | fld.d $fN, … | Caricamento in virgola mobile a 64 bit in $fN (alias dei 64 bit bassi di $vrN) | Sì | Sì |
fld.s | fld.s $fN, … | Caricamento in virgola mobile a 32 bit in $fN (alias dei 32 bit bassi di $vrN) | Sì | Sì |