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

Vulnerabilidad en Kernel de Linux (CVE-2021-47069)

Gravedad CVSS v3.1:
ALTA
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
01/03/2024
Última modificación:
09/01/2025

Descripción

En el kernel de Linux, se resolvió la siguiente vulnerabilidad: ipc/mqueue, msg, sem: evite confiar en una referencia de pila después de su vencimiento do_mq_timedreceive llama a wq_sleep con una dirección local de pila. El remitente (do_mq_timedsend) usa esta dirección para luego llamar a pipelined_send. Esto conduce a una ejecución muy difícil de desencadenar en la que una llamada do_mq_timedreceive puede regresar y dejar que do_mq_timedsend dependa de una dirección no válida, lo que provoca el siguiente bloqueo: RIP: 0010:wake_q_add_safe+0x13/0x60 Seguimiento de llamadas: __x64_sys_mq_timedsend+0x2a9/0x490 do_syscall_64+0x80 /0x680 Entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f5928e40343 La ejecución ocurre como: 1. do_mq_timedreceive llama a wq_sleep con la dirección de `struct ext_wait_queue` en la pila de funciones (alias `ewq_addr` aquí): contiene una `struct ext_wait_queue * válida ` siempre y cuando la pila no haya sido sobrescrita. 2. `ewq_addr` se agrega a info->e_wait_q[RECV].list en wq_add, y do_mq_timedsend lo recibe a través de wq_get_first_waiter(info, RECV) para llamar a __pipelined_op. 3. El remitente llama a __pipelined_op::smp_store_release(&this->state, STATE_READY). Aquí es donde comienza la ventana de ejecución. (`esto` es `ewq_addr`.) 4. Si el receptor se activa ahora en do_mq_timedreceive::wq_sleep, verá `state == STATE_READY` y se interrumpirá. 5. do_mq_timedreceive regresa y ya no se garantiza que `ewq_addr` sea una `struct ext_wait_queue *` ya que estaba en la pila de do_mq_timedreceive. (Aunque es posible que la dirección no se sobrescriba hasta que otra función la toque, lo que significa que puede persistir por un tiempo indefinido). 6. do_mq_timedsend::__pipelined_op() todavía cree que `ewq_addr` es una `struct ext_wait_queue *`, y lo usa para encontrar una task_struct para pasar a la llamada wake_q_add_safe. En el afortunado caso de que nada haya sobrescrito `ewq_addr` todavía, `ewq_addr->task` es la estructura de tarea correcta. En el desafortunado caso, __pipelined_op::wake_q_add_safe recibe una dirección falsa como la task_struct del receptor que causa el bloqueo. do_mq_timedsend::__pipelined_op() no debe eliminar la referencia a "esto" después de configurar STATE_READY, ya que la contraparte del receptor ahora puede regresar. Cambie __pipelined_op para llamar a wake_q_add_safe en el task_struct del receptor devuelto por get_task_struct, en lugar de desreferenciar "this" que se encuentra en la pila del receptor. Como señaló Manfred, la ejecución también existe potencialmente en ipc/msg.c::expunge_all e ipc/sem.c::wake_up_sem_queue_prepare. Arréglelos de la misma manera.

Productos y versiones vulnerables

CPE Desde Hasta
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.6 (incluyendo) 5.10.40 (excluyendo)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (incluyendo) 5.12.7 (excluyendo)
cpe:2.3:o:linux:linux_kernel:5.13:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:5.13:rc2:*:*:*:*:*:*