
Prueba de concepto que demuestra una fuga de datos microarquitectónica en procesadores Loongson LA464/LA664 a través de bits superiores indefinidos de registros vectoriales LASX, similar a ZenBleed.
LoongBleed es una vulnerabilidad de hardware, conceptualmente similar a ZenBleed (CVE-2023-20593) — que afecta a los procesadores Loongson LA464/LA664 que implementan tanto LSX (SIMD de 128 bits) como LASX (SIMD de 256 bits).
En LoongArch, los registros LSX $vr (128 bits) se alias con la mitad inferior de los registros
LASX $xr (256 bits). Las instrucciones LSX y las operaciones básicas de punto flotante
solo están definidas para operar sobre los 128 bits inferiores (o un subconjunto de ellos); los
bits superiores del registro $xr correspondiente son indefinidos. Sin embargo, debido
a un fallo microarquitectónico, estas operaciones pueden filtrar datos a través de los
128 bits superiores de $xr, exponiendo datos sensibles a través de límites de privilegio o
entre hermanos SMT.
Nota sobre el descubrimiento independiente — El mismo fallo de hardware subyacente fue descubierto y publicado de forma independiente por investigadores del CISPA Helmholtz Center for Information Security como LoongLeak (https://loongleakattack.com/), presentado en USENIX Security 2026 como "LoongLeak: Architectural Cross-Privilege-Boundary Data Leakage on LoongArch CPUs". Nuestro trabajo fue desarrollado de forma independiente del equipo de LoongLeak; ambos grupos llegaron a la misma conclusión de que los procesadores Loongson LA464/LA664 filtran datos a través de los bits superiores indefinidos de los registros LASX
$xr. Nótese que las instrucciones que utilizamos para desencadenar la fuga no son idénticas a las reportadas en el artículo de LoongLeak: nuestra PoC se basa en un conjunto diferente de gadgets (vor.v,vld,fld.d,fld.s) para reproducir el mismo fallo de hardware subyacente. Además, dado que la fuga puede desencadenarse mediante instrucciones puramente registro-a-registro comovor.v(sin carga de memoria involucrada), nuestro análisis sugiere que la causa raíz es probablemente la reutilización de registros físicos: los bits superiores de un registro físico reutilizado no se limpian, filtrando datos obsoletos de un ocupante anterior del registro. Esto difiere del análisis del artículo de LoongLeak, que atribuye los datos filtrados a la caché de datos L1.
La prueba de concepto funciona de la siguiente manera:
$xrN mediante xvld.xvst.La PoC ejecuta este gadget repetidamente a través de 16 registros vectoriales arquitectónicos
($xr0–$xr15) en hilos fijados a núcleos físicos. Los valores distintos de cero que
aparecen después de la instrucción indican que la microarquitectura ha propagado
datos obsoletos o de otro contexto al estado de los registros arquitectónicos.
La PoC admite múltiples instrucciones de prueba, seleccionables mediante --gadget:
En LA664, los cuatro gadgets exponen la fuga, filtrando como máximo 192 bits por
vector. En LA464, vld, fld.d y fld.s filtran (como máximo 224 bits por
vector); el gadget predeterminado vor.v no filtra en 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 hilo víctima procesa datos sensibles en una CPU lógica mientras la PoC sondea registros en su hermano SMT. El hilo espía puede observar fragmentos de los datos de la víctima en los bits superiores filtrados.
# 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
Para una configuración automatizada, utilice el script proporcionado:
./poc_la664.sh
Esto genera una carga de trabajo sort en la CPU 1 (el hermano SMT de la CPU 0) y lanza
LoongBleed en la CPU 0 con el gadget predeterminado.
Un hilo víctima procesa datos sensibles en una CPU mientras la PoC sondea
registros en el mismo núcleo. Requiere --gadget vld ya que el gadget
predeterminado vor.v no filtra en 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
Para una configuración automatizada:
./poc_la464.sh
Esto genera una carga de trabajo sort en la CPU 0 y lanza LoongBleed con --gadget vld.
La PoC es un programa C++ de un solo archivo sin dependencias externas.
g++ -std=c++11 -O2 -march=native -pthread -o loongbleed_poc loongbleed_poc.cpp
O utilice el script proporcionado:
./run.sh
# or, on LA464:
./run.sh --gadget vld
Cuando se detecta una fuga y los bytes filtrados contienen una secuencia de al menos 8 caracteres ASCII imprimibles contiguos (0x20–0x7e), la PoC imprime:
[cpu 0] LEAK chunk=14 data=0x7461646e756f4620_6572617774666f53_0000000000000000_0000000000000000 ascii=............Software Foundat
$xr0–$xr15) lo desencadenó$xrN después de la
instrucción, mostrado como data3_data2_data1_data0 donde:
data0 = bits [63:0] (los 64 bits más bajos del resultado)data1 = bits [127:64] (los 64 bits superiores de la mitad inferior de 128 bits)data2 = bits [191:128] (los 64 bits inferiores de la mitad superior de 128 bits)data3 = bits [255:192] (los 64 bits superiores de la mitad superior de 128 bits)..Cualquier valor distinto de cero en los 128 bits superiores (data2 o data3) indica una
fuga de datos microarquitectónica.
La vulnerabilidad se descubrió mientras se leía el artículo de Chips and Cheese "Loongson's LSX and LASX Vector Extensions". El artículo señalaba que las instrucciones vectoriales pueden dejar tras de sí algún residuo de datos aleatorios. Esto nos llevó a plantear la hipótesis de que el renombrado de registros podría no limpiar los registros — un mecanismo similar a ZenBleed — lo que en teoría permitiría filtrar datos del espacio del kernel. Luego realizamos experimentos para verificar esta hipótesis; la fuga efectivamente ocurre y se reproduce tanto en el Loongson 3A5000 como en el 3A6000.
Este proyecto se proporciona únicamente con fines educativos y de investigación de seguridad.
| Gadget | Instrucción | Descripción | Filtra en LA664 | Filtra en LA464 |
|---|
vor | vor.v $vrN, $vrN, $vrN | OR bit a bit de $vrN consigo mismo | Sí | No |
vld | vld $vrN, … | Carga de 128 bits desde memoria a $vrN | Sí | Sí |
fld.d | fld.d $fN, … | Carga de punto flotante de 64 bits a $fN (alias de los 64 bits bajos de $vrN) | Sí | Sí |
fld.s | fld.s $fN, … | Carga de punto flotante de 32 bits a $fN (alias de los 32 bits bajos de $vrN) | Sí | Sí |