fkie_cve-2023-53024
Vulnerability from fkie_nvd
Published
2025-03-27 17:15
Modified
2025-03-28 18:11
Severity ?
Summary
In the Linux kernel, the following vulnerability has been resolved:
bpf: Fix pointer-leak due to insufficient speculative store bypass mitigation
To mitigate Spectre v4, 2039f26f3aca ("bpf: Fix leakage due to
insufficient speculative store bypass mitigation") inserts lfence
instructions after 1) initializing a stack slot and 2) spilling a
pointer to the stack.
However, this does not cover cases where a stack slot is first
initialized with a pointer (subject to sanitization) but then
overwritten with a scalar (not subject to sanitization because
the slot was already initialized). In this case, the second write
may be subject to speculative store bypass (SSB) creating a
speculative pointer-as-scalar type confusion. This allows the
program to subsequently leak the numerical pointer value using,
for example, a branch-based cache side channel.
To fix this, also sanitize scalars if they write a stack slot
that previously contained a pointer. Assuming that pointer-spills
are only generated by LLVM on register-pressure, the performance
impact on most real-world BPF programs should be small.
The following unprivileged BPF bytecode drafts a minimal exploit
and the mitigation:
[...]
// r6 = 0 or 1 (skalar, unknown user input)
// r7 = accessible ptr for side channel
// r10 = frame pointer (fp), to be leaked
//
r9 = r10 # fp alias to encourage ssb
*(u64 *)(r9 - 8) = r10 // fp[-8] = ptr, to be leaked
// lfence added here because of pointer spill to stack.
//
// Ommitted: Dummy bpf_ringbuf_output() here to train alias predictor
// for no r9-r10 dependency.
//
*(u64 *)(r10 - 8) = r6 // fp[-8] = scalar, overwrites ptr
// 2039f26f3aca: no lfence added because stack slot was not STACK_INVALID,
// store may be subject to SSB
//
// fix: also add an lfence when the slot contained a ptr
//
r8 = *(u64 *)(r9 - 8)
// r8 = architecturally a scalar, speculatively a ptr
//
// leak ptr using branch-based cache side channel:
r8 &= 1 // choose bit to leak
if r8 == 0 goto SLOW // no mispredict
// architecturally dead code if input r6 is 0,
// only executes speculatively iff ptr bit is 1
r8 = *(u64 *)(r7 + 0) # encode bit in cache (0: slow, 1: fast)
SLOW:
[...]
After running this, the program can time the access to *(r7 + 0) to
determine whether the chosen pointer bit was 0 or 1. Repeat this 64
times to recover the whole address on amd64.
In summary, sanitization can only be skipped if one scalar is
overwritten with another scalar. Scalar-confusion due to speculative
store bypass can not lead to invalid accesses because the pointer
bounds deducted during verification are enforced using branchless
logic. See 979d63d50c0c ("bpf: prevent out of bounds speculation on
pointer arithmetic") for details.
Do not make the mitigation depend on !env->allow_{uninit_stack,ptr_leaks}
because speculative leaks are likely unexpected if these were enabled.
For example, leaking the address to a protected log file may be acceptable
while disabling the mitigation might unintentionally leak the address
into the cached-state of a map that is accessible to unprivileged
processes.
References
Impacted products
Vendor | Product | Version |
---|
{ "cveTags": [], "descriptions": [ { "lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Fix pointer-leak due to insufficient speculative store bypass mitigation\n\nTo mitigate Spectre v4, 2039f26f3aca (\"bpf: Fix leakage due to\ninsufficient speculative store bypass mitigation\") inserts lfence\ninstructions after 1) initializing a stack slot and 2) spilling a\npointer to the stack.\n\nHowever, this does not cover cases where a stack slot is first\ninitialized with a pointer (subject to sanitization) but then\noverwritten with a scalar (not subject to sanitization because\nthe slot was already initialized). In this case, the second write\nmay be subject to speculative store bypass (SSB) creating a\nspeculative pointer-as-scalar type confusion. This allows the\nprogram to subsequently leak the numerical pointer value using,\nfor example, a branch-based cache side channel.\n\nTo fix this, also sanitize scalars if they write a stack slot\nthat previously contained a pointer. Assuming that pointer-spills\nare only generated by LLVM on register-pressure, the performance\nimpact on most real-world BPF programs should be small.\n\nThe following unprivileged BPF bytecode drafts a minimal exploit\nand the mitigation:\n\n [...]\n // r6 = 0 or 1 (skalar, unknown user input)\n // r7 = accessible ptr for side channel\n // r10 = frame pointer (fp), to be leaked\n //\n r9 = r10 # fp alias to encourage ssb\n *(u64 *)(r9 - 8) = r10 // fp[-8] = ptr, to be leaked\n // lfence added here because of pointer spill to stack.\n //\n // Ommitted: Dummy bpf_ringbuf_output() here to train alias predictor\n // for no r9-r10 dependency.\n //\n *(u64 *)(r10 - 8) = r6 // fp[-8] = scalar, overwrites ptr\n // 2039f26f3aca: no lfence added because stack slot was not STACK_INVALID,\n // store may be subject to SSB\n //\n // fix: also add an lfence when the slot contained a ptr\n //\n r8 = *(u64 *)(r9 - 8)\n // r8 = architecturally a scalar, speculatively a ptr\n //\n // leak ptr using branch-based cache side channel:\n r8 \u0026= 1 // choose bit to leak\n if r8 == 0 goto SLOW // no mispredict\n // architecturally dead code if input r6 is 0,\n // only executes speculatively iff ptr bit is 1\n r8 = *(u64 *)(r7 + 0) # encode bit in cache (0: slow, 1: fast)\nSLOW:\n [...]\n\nAfter running this, the program can time the access to *(r7 + 0) to\ndetermine whether the chosen pointer bit was 0 or 1. Repeat this 64\ntimes to recover the whole address on amd64.\n\nIn summary, sanitization can only be skipped if one scalar is\noverwritten with another scalar. Scalar-confusion due to speculative\nstore bypass can not lead to invalid accesses because the pointer\nbounds deducted during verification are enforced using branchless\nlogic. See 979d63d50c0c (\"bpf: prevent out of bounds speculation on\npointer arithmetic\") for details.\n\nDo not make the mitigation depend on !env-\u003eallow_{uninit_stack,ptr_leaks}\nbecause speculative leaks are likely unexpected if these were enabled.\nFor example, leaking the address to a protected log file may be acceptable\nwhile disabling the mitigation might unintentionally leak the address\ninto the cached-state of a map that is accessible to unprivileged\nprocesses." }, { "lang": "es", "value": "En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: bpf: Fix pointer-leak due to lowest speculative store bypass mitigation Para mitigar Spectre v4, 2039f26f3aca (\"bpf: Fix leakage due to lowest speculative store bypass mitigation\") inserta instrucciones lfence despu\u00e9s de 1) inicializar una ranura de pila y 2) derramar un puntero a la pila. Sin embargo, esto no cubre los casos en los que una ranura de pila se inicializa primero con un puntero (sujeto a depuraci\u00f3n) pero luego se sobrescribe con un escalar (no sujeto a depuraci\u00f3n porque la ranura ya estaba inicializada). En este caso, la segunda escritura puede estar sujeta a la derivaci\u00f3n de almac\u00e9n especulativo (SSB), creando una confusi\u00f3n de tipo de puntero especulativo como escalar. Esto permite que el programa filtre posteriormente el valor del puntero num\u00e9rico utilizando, por ejemplo, un canal lateral de cach\u00e9 basado en bifurcaci\u00f3n. Para solucionar esto, tambi\u00e9n depura los escalares si escriben en una ranura de pila que anteriormente conten\u00eda un puntero. Suponiendo que los derrames de puntero solo son generados por LLVM bajo presi\u00f3n de registro, el impacto en el rendimiento de la mayor\u00eda de los programas BPF del mundo real deber\u00eda ser m\u00ednimo. El siguiente c\u00f3digo de bytes BPF sin privilegios describe un exploit m\u00ednimo y su mitigaci\u00f3n: [...] // r6 = 0 o 1 (escalar, entrada de usuario desconocida) // r7 = ptr accesible para canal lateral // r10 = puntero de trama (fp), a filtrar // r9 = r10 # alias de fp para fomentar ssb *(u64 *)(r9 - 8) = r10 // fp[-8] = ptr, a filtrar // Se a\u00f1adi\u00f3 lfence debido al derrame de puntero a la pila. // // Omitido: bpf_ringbuf_output() ficticio para entrenar el predictor de alias // para la ausencia de dependencia entre r9 y r10. // *(u64 *)(r10 - 8) = r6 // fp[-8] = escalar, sobrescribe ptr // 2039f26f3aca: no se agreg\u00f3 lfence porque la ranura de pila no era STACK_INVALID, // el almacenamiento puede estar sujeto a SSB // // correcci\u00f3n: tambi\u00e9n se agrega una lfence cuando la ranura conten\u00eda un ptr // r8 = *(u64 *)(r9 - 8) // r8 = arquitect\u00f3nicamente un escalar, especulativamente un ptr // // fuga de ptr usando el canal lateral de cach\u00e9 basado en ramas: r8 \u0026amp;= 1 // elige el bit a fugar si r8 == 0 goto SLOW // sin predicci\u00f3n err\u00f3nea // c\u00f3digo arquitect\u00f3nicamente muerto si la entrada r6 es 0, // solo se ejecuta especulativamente si el bit ptr es 1 r8 = *(u64 *)(r7 + 0) # codificar bit en cach\u00e9 (0: lento, 1: r\u00e1pido) SLOW: [...] Despu\u00e9s de ejecutar esto, el programa Puede cronometrar el acceso a *(r7 + 0) para determinar si el bit de puntero seleccionado era 0 o 1. Repita esto 64 veces para recuperar la direcci\u00f3n completa en amd64. En resumen, la depuraci\u00f3n solo se puede omitir si un escalar se sobrescribe con otro. La confusi\u00f3n escalar debido a la omisi\u00f3n del almacenamiento especulativo no puede conducir a accesos inv\u00e1lidos porque los l\u00edmites del puntero deducidos durante la verificaci\u00f3n se aplican mediante l\u00f3gica sin ramificaciones. Consulte 979d63d50c0c (\"bpf: evitar especulaci\u00f3n fuera de los l\u00edmites en aritm\u00e9tica de punteros\") para obtener m\u00e1s detalles. No haga que la mitigaci\u00f3n dependa de !env-\u0026gt;allow_{uninit_stack,ptr_leaks} porque es probable que se produzcan fugas especulativas inesperadas si se habilitan. Por ejemplo, filtrar la direcci\u00f3n a un archivo de registro protegido puede ser aceptable, mientras que deshabilitar la mitigaci\u00f3n podr\u00eda filtrar involuntariamente la direcci\u00f3n al estado en cach\u00e9 de un mapa al que pueden acceder procesos sin privilegios." } ], "id": "CVE-2023-53024", "lastModified": "2025-03-28T18:11:40.180", "metrics": {}, "published": "2025-03-27T17:15:51.980", "references": [ { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/01bdcc73dbe7be3ad4d4ee9a59b71e42f461a528" }, { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/81b3374944d201872cfcf82730a7860f8e7c31dd" }, { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/aae109414a57ab4164218f36e2e4a17f027fcaaa" }, { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/b0c89ef025562161242a7c19b213bd6b272e93df" }, { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/da75dec7c6617bddad418159ffebcb133f008262" }, { "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "url": "https://git.kernel.org/stable/c/e4f4db47794c9f474b184ee1418f42e6a07412b6" } ], "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "vulnStatus": "Awaiting Analysis" }
Loading…
Loading…
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.
Loading…
Loading…