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

Vulnerabilidad en Linux (CVE-2023-54271)

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

Descripción

En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:<br /> <br /> blk-cgroup: Corrección de desreferencia NULL causada por la instalación de blkg_policy_data antes de la inicialización<br /> <br /> blk-iocost a veces causa el siguiente fallo:<br /> <br /> BUG: desreferencia de puntero NULL del kernel, dirección: 00000000000000e0<br /> ...<br /> RIP: 0010:_raw_spin_lock+0x17/0x30<br /> Code: be 01 02 00 00 e8 79 38 39 ff 31 d2 89 d0 5d c3 0f 1f 00 0f 1f 44 00 00 55 48 89 e5 65 ff 05 48 d0 34 7e b9 01 00 00 00 31 c0 0f b1 0f 75 02 5d c3 89 c6 e8 ea 04 00 00 5d c3 0f 1f 84 00 00<br /> RSP: 0018:ffffc900023b3d40 EFLAGS: 00010046<br /> RAX: 0000000000000000 RBX: 00000000000000e0 RCX: 0000000000000001<br /> RDX: ffffc900023b3d20 RSI: ffffc900023b3cf0 RDI: 00000000000000e0<br /> RBP: ffffc900023b3d40 R08: ffffc900023b3c10 R09: 0000000000000003<br /> R10: 0000000000000064 R11: 000000000000000a R12: ffff888102337000<br /> R13: fffffffffffffff2 R14: ffff88810af408c8 R15: ffff8881070c3600<br /> FS: 00007faaaf364fc0(0000) GS:ffff88842fdc0000(0000) knlGS:0000000000000000<br /> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br /> CR2: 00000000000000e0 CR3: 00000001097b1000 CR4: 0000000000350ea0<br /> Call Trace:<br /> <br /> ioc_weight_write+0x13d/0x410<br /> cgroup_file_write+0x7a/0x130<br /> kernfs_fop_write_iter+0xf5/0x170<br /> vfs_write+0x298/0x370<br /> ksys_write+0x5f/0xb0<br /> __x64_sys_write+0x1b/0x20<br /> do_syscall_64+0x3d/0x80<br /> entry_SYSCALL_64_after_hwframe+0x46/0xb0<br /> <br /> Esto ocurre porque iocg-&amp;gt;ioc es NULL. El campo es inicializado por ioc_pd_init() y nunca se borra. La desreferencia NULL es causada por blkcg_activate_policy() al instalar blkg_policy_data antes de inicializarlo.<br /> <br /> blkcg_activate_policy() estaba haciendo lo siguiente:<br /> <br /> 1. Asignar pd&amp;#39;s para todos los blkg&amp;#39;s existentes e instalarlos en blkg-&amp;gt;pd[].<br /> 2. Inicializar todos los pd&amp;#39;s.<br /> 3. Poner en línea todos los pd&amp;#39;s.<br /> <br /> blkcg_activate_policy() solo toma el queue_lock y puede liberar y volver a adquirir el bloqueo ya que la asignación puede necesitar dormir. ioc_weight_write() toma blkcg-&amp;gt;lock e itera sobre todos sus blkg&amp;#39;s. Los dos pueden competir y si ioc_weight_write() se ejecuta durante el #1 o entre el #1 y el #2, puede encontrar un pd que aún no está inicializado, lo que lleva a un fallo.<br /> <br /> El fallo puede ser reproducido con el siguiente script:<br /> <br /> #!/bin/bash<br /> <br /> echo +io &amp;gt; /sys/fs/cgroup/cgroup.subtree_control<br /> systemd-run --unit touch-sda --scope dd if=/dev/sda of=/dev/null bs=1M count=1 iflag=direct<br /> echo 100 &amp;gt; /sys/fs/cgroup/system.slice/io.weight<br /> bash -c "echo &amp;#39;8:0 enable=1&amp;#39; &amp;gt; /sys/fs/cgroup/io.cost.qos" &amp;amp;<br /> sleep .2<br /> echo 100 &amp;gt; /sys/fs/cgroup/system.slice/io.weight<br /> <br /> con el siguiente parche aplicado:<br /> <br /> &amp;gt; diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c<br /> &amp;gt; index fc49be622e05..38d671d5e10c 100644<br /> &amp;gt; --- a/block/blk-cgroup.c<br /> &amp;gt; +++ b/block/blk-cgroup.c<br /> &amp;gt; @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)<br /> &amp;gt; pd-&amp;gt;online = false;<br /> &amp;gt; }<br /> &amp;gt;<br /> &amp;gt; + if (system_state == SYSTEM_RUNNING) {<br /> &amp;gt; + spin_unlock_irq(&amp;amp;q-&amp;gt;queue_lock);<br /> &amp;gt; + ssleep(1);<br /> &amp;gt; + spin_lock_irq(&amp;amp;q-&amp;gt;queue_lock);<br /> &amp;gt; + }<br /> &amp;gt; +<br /> &amp;gt; /* all allocated, init in the same order */<br /> &amp;gt; if (pol-&amp;gt;pd_init_fn)<br /> &amp;gt; list_for_each_entry_reverse(blkg, &amp;amp;q-&amp;gt;blkg_list, q_node)<br /> <br /> No veo una razón por la cual todos los pd&amp;#39;s deban ser asignados, inicializados y puestos en línea juntos. El único requisito de orden es que los blkg&amp;#39;s padre sean inicializados y puestos en línea antes que los hijos, lo cual está garantizado por el orden de recorrido. Corrijamos el error al asignar, inicializar y poner en línea el pd para cada blkg y manteniendo blkcg-&amp;gt;lock durante la inicialización y la puesta en línea. Esto asegura que un blkg instalado esté siempre completamente inicializado y puesto en línea, eliminando la ventana de carrera.

Impacto