Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2022-50650

Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
09/12/2025
Última modificación:
09/12/2025

Descripción

*** 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 &gt; 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&amp;#39;s PTR_TO_STACK, we still have to<br /> copy caller&amp;#39;s reference_state to callback&amp;#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 -&gt; cb1 -&gt; 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-&gt;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).

Impacto