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-&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&#39;s para todos los blkg&#39;s existentes e instalarlos en blkg-&gt;pd[].<br />
2. Inicializar todos los pd&#39;s.<br />
3. Poner en línea todos los pd&#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-&gt;lock e itera sobre todos sus blkg&#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 &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 &gt; /sys/fs/cgroup/system.slice/io.weight<br />
bash -c "echo &#39;8:0 enable=1&#39; &gt; /sys/fs/cgroup/io.cost.qos" &amp;<br />
sleep .2<br />
echo 100 &gt; /sys/fs/cgroup/system.slice/io.weight<br />
<br />
con el siguiente parche aplicado:<br />
<br />
&gt; diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c<br />
&gt; index fc49be622e05..38d671d5e10c 100644<br />
&gt; --- a/block/blk-cgroup.c<br />
&gt; +++ b/block/blk-cgroup.c<br />
&gt; @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)<br />
&gt; pd-&gt;online = false;<br />
&gt; }<br />
&gt;<br />
&gt; + if (system_state == SYSTEM_RUNNING) {<br />
&gt; + spin_unlock_irq(&amp;q-&gt;queue_lock);<br />
&gt; + ssleep(1);<br />
&gt; + spin_lock_irq(&amp;q-&gt;queue_lock);<br />
&gt; + }<br />
&gt; +<br />
&gt; /* all allocated, init in the same order */<br />
&gt; if (pol-&gt;pd_init_fn)<br />
&gt; list_for_each_entry_reverse(blkg, &amp;q-&gt;blkg_list, q_node)<br />
<br />
No veo una razón por la cual todos los pd&#39;s deban ser asignados, inicializados y puestos en línea juntos. El único requisito de orden es que los blkg&#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-&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.



