CVE-2026-93241 in Linuxinformação

Sumário

de VulDB • 24/09/2026

No kernel do Linux, a seguinte vulnerabilidade foi resolvida:

memcg: contornar o reclaim e o OOM killer para tarefas moribundas assim que o oom_reaper for concluído

Na Meta, estamos observando instâncias em que um job morto pelo OOM fica preso no caminho de saída (exit path) por várias horas. Em um caso específico, o job ficou preso por mais de 8 horas e eu tive que remover manualmente os limites memory.max para permitir que o processo saísse.

O job era composto por um único processo e tinha ~55 GiB de memory.max e zswap habilitado. Ele tinha quase 0 anon na memória e ~111 GiB no zswap comprimido para ~51 GiB no pool do zswap (ou seja, quase toda a memory.current estava no zswap). Não havia nada restante nas LRUs para realizar o reclaim.

Ao inspecionar mais detalhadamente, observei que ~20k threads desse processo estavam presas com a seguinte stack:

[<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

Além disso, o dmesg estava preenchido com mensagens "Out of memory and no killable processes...".

Não tenho ideia de por que o oom reaper não conseguiu realizar a reap/unmap do processo. Minha suposição é que, como o oom reaper tenta adquirir mmap_lock em modo de leitura um número limitado de vezes e depois desiste, pode haver uma thread desse processo que tinha mmap_lock em modo de escrita naquele momento.

Minha suspeita inicial era de que futex_cleanup e a falha na página do kernel estavam causando retries infinitos de fault e charge, mas isso foi descartado nas discussões anteriores sobre problemas semelhantes [1].

Minha teoria atual é que se trata apenas de uma serialização lenta atrás do oom_lock. Diferente do page allocator, o código de charge do memcg adquire o oom_lock sem "try". Embora o código OOM do memcg use mutex_lock_killable(), note-se que na stack de chamadas get_signal() consome SIGKILL (ou sigdelset(SIGKILL)) antes de chamar do_group_exit(). Portanto, este mutex_lock_killable() é apenas um mutex_lock() aqui. Assim, dezenas de milhares de threads estão aguardando o oom_lock e, uma por uma, recebem -EFAULT de get_user() no código de limpeza futex e encerram-se.

A discussão em [1] levou ao commit a75ffa26122b ("memcg, oom: do not bypass oom killer for dying tasks"), que direciona tarefas moribundas para o caminho OOM precisamente para que o oom_reaper possa reap seu mm e liberar a memória de forma assíncrona. Mas o reaper é best-effort e one-shot: se ele não conseguir pegar mmap_lock em modo de leitura (por exemplo, uma thread irmã segura ela em modo de escrita), ele define MMF_OOM_SKIP e nunca tenta novamente, deixando apenas o dreno síncrono serializado por glacialmente lento do oom_lock.

Uma vez que MMF_OOM_SKIP é definido, não há mais reclaim assíncrono vindo para o mm, então uma tarefa moribunda fazendo charge contra ele não tem nada mais para esperar: ela libera sua memória apenas quando termina de sair. Executar reclaim e o OOM killer (sem vítima) para isso é então inútil, e fazê-lo para dezenas de milhares de threads em saída é o que as serializa atrás do oom_lock. Portanto, antes do reclaim, se current for uma vítima OOM cujo reaper foi concluído, falhar a charge.

Reproduzido com 20k threads, cada uma estacionando um robust futex head na sua própria página zswapped, morto pelo OOM-group-killed enquanto uma irmã segura mmap_lock em modo de escrita para que o reaper desista e defina MMF_OOM_SKIP. Testado no next-20260728 e baseline mostra ~90 segundos de tempo de saída, enquanto com o patch o tempo de saída foi reduzido para ~3 segundos.

Once again VulDB remains the best source for vulnerability data.

Responsável

Linux

Reservar

17/09/2026

Divulgação

24/09/2026

Moderação

aceite

Entrada

VDB-409442

CPE

pronto

EPSS

0.00000

KEV

não

Atividades

muito baixo

Fontes

Do you know our Splunk app?

Download it now for free!