Vulnerabilidad en Linux (CVE-2026-23157)
Fecha de publicación:
14/02/2026
En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta: btrfs: no requerir estrictamente el umbral de metadatos sucios para la escritura de páginas de metadatos [ERROR] Existe un informe interno de que más de 1000 procesos están esperando en el io_schedule_timeout() de balance_dirty_pages(), causando un cuelgue del sistema y desencadenando un volcado de memoria del kernel. El kernel está basado en el kernel v6.4, pero el problema raíz todavía se aplica a cualquier kernel upstream anterior a la v6.18. [CAUSA] De Jan Kara por su sabiduría sobre el comportamiento de balanceo de páginas sucias primero. Este límite de suciedad del cgroup era lo que realmente estaba desempeñando el papel aquí porque el cgroup tenía solo una pequeña cantidad de memoria y por lo tanto el límite de suciedad para él era de aproximadamente 16MB. La limitación de suciedad es responsable de asegurar que nadie pueda ensuciar (significativamente) más memoria sucia de lo que hay de límite de suciedad. Así, cuando una tarea está ensuciando páginas, entra periódicamente en balance_dirty_pages() y la dejamos dormir allí para ralentizar el ensuciamiento. Cuando el sistema ya está por encima del límite de suciedad (ya sea globalmente o dentro de un cgroup de la tarea en ejecución), no permitiremos que la tarea salga de balance_dirty_pages() hasta que el número de páginas sucias caiga por debajo del límite. Así que en este caso particular, como ya mencioné, había un cgroup con una cantidad de memoria relativamente pequeña y como resultado con un límite de suciedad establecido en 16MB. Una tarea de ese cgroup ha ensuciado páginas por un valor de aproximadamente 28MB en el inodo btree de btrfs y estas eran prácticamente las únicas páginas sucias en ese cgroup. Así que eso significa que la única forma de reducir las páginas sucias de ese cgroup es realizar el writeback de las páginas sucias del inodo btree de btrfs, y solo después de eso esos procesos pueden salir de balance_dirty_pages(). Ahora volviendo a la parte de btrfs, btree_writepages() es responsable de realizar el writeback de las páginas sucias del inodo btree. El problema aquí es que hay un umbral interno de btrfs que si los bytes sucios del inodo btree están por debajo del umbral de 32M, no realizará ningún writeback. Este comportamiento es para agrupar la mayor cantidad posible de metadatos para que no escribamos de vuelta esos bloques de árbol y luego los volvamos a copiar en escritura (re-COW) para otra modificación. Estos 32MiB internos son más altos que el tamaño de página sucia existente (28MiB), lo que significa que no se realizará ningún writeback, causando un interbloqueo entre btrfs y cgroup: - Btrfs no quiere realizar el writeback del inodo btree hasta que haya más páginas sucias - Cgroup/MM no quiere más páginas sucias para el inodo btree de btrfs Así, cualquier proceso que toque ese inodo btree es puesto a dormir hasta que el número de páginas sucias se reduzca. Muchas gracias a Jan Kara por el análisis de la causa raíz. [MEJORA] Desde el commit del kernel b55102826d7d ('btrfs: establecer AS_KERNEL_FILE en el btree_inode'), las páginas del inodo btree de btrfs solo se cargarán al cgroup raíz, el cual debería tener un límite mucho mayor que el umbral de 32MiB de btrfs. Así que no debería afectar a kernels más nuevos. Pero para todos los kernels LTS actuales, todos están afectados por este problema, y realizar un backport de todo el AS_KERNEL_FILE puede no ser una buena idea. Incluso para kernels más nuevos, sigo pensando que es una buena idea eliminar el umbral interno en btree_writepages(), ya que en la mayoría de los casos cgroup/MM tiene una mejor visión del uso de la memoria de todo el sistema que el umbral fijo de btrfs. Para los llamadores internos que usan btrfs_btree_balance_dirty(), ya que esa función ya está realizando una comprobación de umbral interna, ---truncado---
Gravedad: Pendiente de análisis
Última modificación:
18/02/2026