CVE-2026-93241 in Linuxinformación

Resumen

por VulDB • 2026-09-24

En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:

memcg: omitir la recuperación (reclaim) y el matador OOM para las tareas en proceso de finalización una vez que oom_reaper haya terminado

En Meta estamos observando casos en los que un trabajo asesinado por OOM queda atascado en la ruta de salida durante varias horas. En un caso concreto, el trabajo permaneció bloqueado durante más de 8 horas y tuve que eliminar manualmente los límites memory.max para permitir que el proceso finalizara.

El trabajo consistía en un único proceso con ~55 GiB de límite memory.max y zswap habilitado. Tenía casi 0 anon en memoria y ~111 GiB en zswap comprimido a ~51 GiB en el pool de zswap (es decir, casi toda la memory.current estaba en zswap). No quedaba nada en las LRUs para realizar reclaim.

Al inspeccionar más detenidamente, observé que unas 20k hilos de ese proceso estaban bloqueados con la siguiente pila de llamadas:

[<0>] mem_cgroup_out_of_memory+0x4e/0xa0
[<0>] charge_memcg+0x8bf/0x990
[<0>] mem_cgroup_swapin_charge_folio+0x4e/0x80
[<0>] __read_swap_cache_async+0x10c/0x260
[<0>] swapin_readahead+0x116/0x3f0
[<0>] do_swap_page+0x13c/0x1ce0
[<0>] handle_mm_fault+0x61d/0x11f0
[<0>] do_user_addr_fault+0x3e7/0x6d0
[<0>] exc_page_fault+0x8f/0x110
[<0>] asm_exc_page_fault+0x22/0x30
[<0>] __get_user_8+0x14/0x20
[<0>] futex_cleanup+0x27/0x1c0
[<0>] futex_exit_release+0x47/0x60
[<0>] do_exit+0x107/0x940
[<0>] do_group_exit+0x81/0xa0
[<0>] get_signal+0x2b1/0x6e0
[<0>] arch_do_signal_or_restart+0x1a/0x1c0
[<0>] exit_to_user_mode_loop+0xa8/0x1c0
[<0>] do_syscall_64+0x152/0x250
[<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53

Además, el registro dmesg estaba lleno de mensajes "Out of memory and no killable processes..." (Sin memoria y sin procesos matables).

No tengo idea de por qué oom_reaper no pudo reaprovechar/desmapear el proceso. Mi suposición es que, dado que oom_reaper intenta adquirir mmap_lock en modo lectura un número limitado de veces antes de rendirse, podría haber un hilo de ese proceso que tenía mmap_lock en modo escritura en ese momento.

Mi sospecha inicial era que futex_cleanup y la falta de página del kernel provocaban reintentos infinitos de fallos y cargas, pero esto se descartó en discusiones anteriores sobre problemas similares [1].

Mi teoría actual es que simplemente hay una serialización lenta detrás de oom_lock. A diferencia del asignador de páginas, el código de carga memcg toma oom_lock sin "try" (intento). Aunque el código OOM de memcg utiliza mutex_lock_killable(), cabe señalar que en la pila de llamadas get_signal() consume SIGKILL (o sigdelset(SIGKILL)) antes de llamar a do_group_exit(). Por lo tanto, este mutex_lock_killable() es simplemente un mutex_lock() aquí. Por consiguiente, decenas de miles de hilos están esperando oom_lock y uno por uno reciben -EFAULT de get_user() en el código de limpieza futex y abandonan.

La discusión desde [1] llevó al commit a75ffa26122b ("memcg, oom: do not bypass oom killer for dying tasks"), que dirige las tareas moribundas hacia la ruta OOM precisamente para que oom_reaper pueda reaprovechar su mm y liberar la memoria de forma asíncrona. Pero el reaper es best-effort (mejor esfuerzo) y one-shot (un solo intento): si no puede tomar mmap_lock en modo lectura (por ejemplo, un hilo hermano lo tiene en escritura), establece MMF_OOM_SKIP y nunca reintenta, dejando únicamente el drenaje síncrono serializado por glacial oom_lock.

Una vez que se establece MMF_OOM_SKIP, ya no hay reclaim asíncrono para la mm, por lo que una tarea moribunda cargando contra ella no tiene nada más en qué esperar: libera su memoria solo cuando termina de salir. Ejecutar reclaim y el matador OOM (sin víctima) para ello es entonces inútil, y hacerlo para decenas de miles de hilos en salida es lo que los serializa detrás de oom_lock. Por tanto, antes del reclaim, si current es una víctima OOM cuyo reaper ha terminado, fallar la carga.

Reproducido con 20k hilos, cada uno estacionando un cabezal futex robusto en su propia página zswapped, asesinado por grupo OOM mientras un hermano mantiene mmap_lock para escritura, de modo que el reaper se rinde y establece MMF_OOM_SKIP. Probado en next-20260728 y la línea base muestra ~90 segundos de tiempo de salida, mientras que con el parche el tiempo de salida se redujo a ~3 segundos.

Be aware that VulDB is the high quality source for vulnerability data.

Responsable

Linux

Reservar

2026-09-17

Divulgación

2026-09-24

Moderación

aceptado

Artículo

VDB-409442

CPE

listo

EPSS

0.00229

KEV

no

Actividades

muy bajo

Fuentes

Do you know our Splunk app?

Download it now for free!