// For flags

CVE-2023-52828

bpf: Detect IP == ksym.end as part of BPF program

Severity Score

6.6
*CVSS v3.1

Exploit Likelihood

*EPSS

Affected Versions

*CPE

Public Exploits

0
*Multiple Sources

Exploited in Wild

-
*KEV

Decision

Track
*SSVC
Descriptions

In the Linux kernel, the following vulnerability has been resolved:

bpf: Detect IP == ksym.end as part of BPF program

Now that bpf_throw kfunc is the first such call instruction that has
noreturn semantics within the verifier, this also kicks in dead code
elimination in unprecedented ways. For one, any instruction following
a bpf_throw call will never be marked as seen. Moreover, if a callchain
ends up throwing, any instructions after the call instruction to the
eventually throwing subprog in callers will also never be marked as
seen.

The tempting way to fix this would be to emit extra 'int3' instructions
which bump the jited_len of a program, and ensure that during runtime
when a program throws, we can discover its boundaries even if the call
instruction to bpf_throw (or to subprogs that always throw) is emitted
as the final instruction in the program.

An example of such a program would be this:

do_something():
...
r0 = 0
exit

foo():
r1 = 0
call bpf_throw
r0 = 0
exit

bar(cond):
if r1 != 0 goto pc+2
call do_something
exit
call foo
r0 = 0 // Never seen by verifier
exit //

main(ctx):
r1 = ...
call bar
r0 = 0
exit

Here, if we do end up throwing, the stacktrace would be the following:

bpf_throw
foo
bar
main

In bar, the final instruction emitted will be the call to foo, as such,
the return address will be the subsequent instruction (which the JIT
emits as int3 on x86). This will end up lying outside the jited_len of
the program, thus, when unwinding, we will fail to discover the return
address as belonging to any program and end up in a panic due to the
unreliable stack unwinding of BPF programs that we never expect.

To remedy this case, make bpf_prog_ksym_find treat IP == ksym.end as
part of the BPF program, so that is_bpf_text_address returns true when
such a case occurs, and we are able to unwind reliably when the final
instruction ends up being a call instruction.

En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: bpf: Detectar IP == ksym.end como parte del programa BPF. Ahora que bpf_throw kfunc es la primera instrucción de llamada que no tiene semántica de retorno dentro del verificador, esto también activa el código muerto eliminación de formas sin precedentes. Por un lado, cualquier instrucción que siga a una llamada a bpf_throw nunca se marcará como vista. Además, si una cadena de llamadas termina lanzándose, cualquier instrucción posterior a la instrucción de llamada al subprog que finalmente se lance en las personas que llaman tampoco se marcará como vista. La forma tentadora de solucionar este problema sería emitir instrucciones 'int3' adicionales que superen el jited_len de un programa y garantizar que, durante el tiempo de ejecución, cuando se inicia un programa, podamos descubrir sus límites incluso si la instrucción de llamada a bpf_throw (o a subprogs que siempre tirar) se emite como instrucción final en el programa. Un ejemplo de un programa de este tipo sería este: do_something(): ... r0 = 0 salir foo(): r1 = 0 llamar a bpf_throw r0 = 0 salir de la barra (cond): si r1 != 0 ir a pc+2 llamar a hacer_algo exit call foo r0 = 0 // Nunca visto por el verificador exit // main(ctx): r1 = ... call bar r0 = 0 exit Aquí, si terminamos lanzando, el seguimiento de pila sería el siguiente: bpf_throw foo bar main En bar, la instrucción final emitida será la llamada a foo, como tal, la dirección de retorno será la instrucción posterior (que el JIT emite como int3 en x86). Esto terminará quedando fuera del jited_len del programa, por lo tanto, al desenrollarlo, no podremos descubrir que la dirección del remitente pertenece a ningún programa y terminaremos en pánico debido al desenrollado poco confiable de la pila de programas BPF que nunca esperamos. Para remediar este caso, haga que bpf_prog_ksym_find trate IP == ksym.end como parte del programa BPF, de modo que is_bpf_text_address devuelva verdadero cuando ocurra tal caso, y podamos desenredarlo de manera confiable cuando la instrucción final termine siendo una instrucción de llamada.

*Credits: N/A
CVSS Scores
Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
Low
Availability
Low
* Common Vulnerability Scoring System
SSVC
  • Decision:Track
Exploitation
None
Automatable
No
Tech. Impact
Partial
* Organization's Worst-case Scenario
Timeline
  • 2024-05-21 CVE Reserved
  • 2024-05-21 CVE Published
  • 2024-05-22 EPSS Updated
  • 2024-11-05 CVE Updated
  • ---------- Exploited in Wild
  • ---------- KEV Due Date
  • ---------- First Exploit
CWE
CAPEC
Affected Vendors, Products, and Versions
Vendor Product Version Other Status
Vendor Product Version Other Status <-- --> Vendor Product Version Other Status
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 5.10.202
Search vendor "Linux" for product "Linux Kernel" and version " < 5.10.202"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 5.15.140
Search vendor "Linux" for product "Linux Kernel" and version " < 5.15.140"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 6.1.64
Search vendor "Linux" for product "Linux Kernel" and version " < 6.1.64"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 6.5.13
Search vendor "Linux" for product "Linux Kernel" and version " < 6.5.13"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 6.6.3
Search vendor "Linux" for product "Linux Kernel" and version " < 6.6.3"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
< 6.7
Search vendor "Linux" for product "Linux Kernel" and version " < 6.7"
en
Affected