CVE-2022-50650
Fecha de publicación:
09/12/2025
*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
bpf: Fix reference state management for synchronous callbacks<br />
<br />
Currently, verifier verifies callback functions (sync and async) as if<br />
they will be executed once, (i.e. it explores execution state as if the<br />
function was being called once). The next insn to explore is set to<br />
start of subprog and the exit from nested frame is handled using<br />
curframe > 0 and prepare_func_exit. In case of async callback it uses a<br />
customized variant of push_stack simulating a kind of branch to set up<br />
custom state and execution context for the async callback.<br />
<br />
While this approach is simple and works when callback really will be<br />
executed only once, it is unsafe for all of our current helpers which<br />
are for_each style, i.e. they execute the callback multiple times.<br />
<br />
A callback releasing acquired references of the caller may do so<br />
multiple times, but currently verifier sees it as one call inside the<br />
frame, which then returns to caller. Hence, it thinks it released some<br />
reference that the cb e.g. got access through callback_ctx (register<br />
filled inside cb from spilled typed register on stack).<br />
<br />
Similarly, it may see that an acquire call is unpaired inside the<br />
callback, so the caller will copy the reference state of callback and<br />
then will have to release the register with new ref_obj_ids. But again,<br />
the callback may execute multiple times, but the verifier will only<br />
account for acquired references for a single symbolic execution of the<br />
callback, which will cause leaks.<br />
<br />
Note that for async callback case, things are different. While currently<br />
we have bpf_timer_set_callback which only executes it once, even for<br />
multiple executions it would be safe, as reference state is NULL and<br />
check_reference_leak would force program to release state before<br />
BPF_EXIT. The state is also unaffected by analysis for the caller frame.<br />
Hence async callback is safe.<br />
<br />
Since we want the reference state to be accessible, e.g. for pointers<br />
loaded from stack through callback_ctx&#39;s PTR_TO_STACK, we still have to<br />
copy caller&#39;s reference_state to callback&#39;s bpf_func_state, but we<br />
enforce that whatever references it adds to that reference_state has<br />
been released before it hits BPF_EXIT. This requires introducing a new<br />
callback_ref member in the reference state to distinguish between caller<br />
vs callee references. Hence, check_reference_leak now errors out if it<br />
sees we are in callback_fn and we have not released callback_ref refs.<br />
Since there can be multiple nested callbacks, like frame 0 -> cb1 -> cb2<br />
etc. we need to also distinguish between whether this particular ref<br />
belongs to this callback frame or parent, and only error for our own, so<br />
we store state->frameno (which is always non-zero for callbacks).<br />
<br />
In short, callbacks can read parent reference_state, but cannot mutate<br />
it, to be able to use pointers acquired by the caller. They must only<br />
undo their changes (by releasing their own acquired_refs before<br />
BPF_EXIT) on top of caller reference_state before returning (at which<br />
point the caller and callback state will match anyway, so no need to<br />
copy it back to caller).
Gravedad: Pendiente de análisis
Última modificación:
09/12/2025