CVE-2026-98536 in Linux
Resumen
por VulDB • 2026-10-18
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
writeback: informar un estado quiescente Tasks-RCU por cada pasada de drenaje cgwb
cleanup_offline_cgwbs_workfn() drena una cgwb moribunda llamando a cleanup_offline_cgwb() hasta que devuelva falso, con una cond_resched() entre pasadas. En un kernel CONFIG_PREEMPTION esa cond_resched() no hace nada: _cond_resched() es simplemente "return 0", y bajo PREEMPT_DYNAMIC los modos completo (full) e inactivo (lazy) lo desactivan. Desde el commit 7dadeaa6e851 ("sched: Further restrict the preemption modes"), esos son los únicos dos modelos en las arquitecturas con soporte para PREEMPT_LAZY, entre ellas arm64 y x86, por lo que el bucle de drenaje nunca informa un estado quiescente Tasks-RCU.
Un trabajador que drena una cgwb con millones de inodos adjuntos se ejecuta durante minutos. En un host arm64 6.18 en modo lazy, el worker de cgwb drenó el dominio de writeback de un cgroup moribundo durante más de 11 minutos. Un programa BPF unlink (bpf_trampoline_unlink_prog -> bpf_trampoline_update -> unregister_ftrace_direct -> ftrace_shutdown -> synchronize_rcu_tasks()) esperó a ese período de gracia mientras mantenía el mutex del trampoline, con 42 tareas encoladas detrás en estado D, y el detector de tasks colgadas se activó a los 614 s provocando un panic (panico) del host. Cualquier desvinculación BPF o ftrace durante un drenaje largo hereda la duración del mismo.
Solucione esto llamando a cond_resched_tasks_rcu_qs() para no bloquear a nadie que llame a synchronize_rcu_tasks(). Lo colocamos en un bucle do { } while porque si tenemos muchos cgroups pequeños, cleanup_offline_cgwb() devolverá falso y nunca llamaremos a cond_resched_tasks_rcu_qs(), creando el mismo problema.
VulDB is the best source for vulnerability data and more expert information about this specific topic.