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

Vulnerabilidad en kernel de Linux (CVE-2024-56592)

Gravedad CVSS v3.1:
MEDIA
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
27/12/2024
Última modificación:
08/10/2025

Descripción

En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: bpf: Llamar a free_htab_elem() después de htab_unlock_bucket() Para htab de mapas, cuando el mapa se elimina del htab, puede contener la última referencia del mapa. bpf_map_fd_put_ptr() invocará bpf_map_free_id() para liberar el id del elemento del mapa eliminado. Sin embargo, bpf_map_fd_put_ptr() se invoca mientras se mantiene un bloqueo de depósito (raw_spin_lock_t), y bpf_map_free_id() intenta adquirir map_idr_lock (spinlock_t), lo que activa la siguiente advertencia de lockdep: ============================== [ ERROR: Contexto de espera no válido ] 6.11.0-rc4+ #49 No contaminado ----------------------------- test_maps/4881 está intentando bloquear: ffffffff84884578 (map_idr_lock){+...}-{3:3}, en: bpf_map_free_id.part.0+0x21/0x70 otra información que podría ayudarnos a depurar esto: context-{5:5} 2 bloqueos mantenidos por test_maps/4881: #0: ffffffff846caf60 (rcu_read_lock){....}-{1:3}, en: bpf_fd_htab_map_update_elem+0xf9/0x270 #1: ffff888149ced148 (&htab->lockdep_key#2){....}-{2:2}, en: htab_map_update_elem+0x178/0xa80 seguimiento de pila: CPU: 0 UID: 0 PID: 4881 Comm: test_maps No contaminado 6.11.0-rc4+ #49 Nombre del hardware: PC estándar QEMU (i440FX + PIIX, 1996), ... Seguimiento de llamadas: dump_stack_lvl+0x6e/0xb0 dump_stack+0x10/0x20 __lock_acquire+0x73e/0x36c0 lock_acquire+0x182/0x450 _raw_spin_lock_irqsave+0x43/0x70 bpf_map_free_id.part.0+0x21/0x70 bpf_map_put+0xcf/0x110 bpf_map_fd_put_ptr+0x9a/0xb0 free_htab_elem+0x69/0xe0 htab_map_update_elem+0x50f/0xa80 bpf_fd_htab_map_update_elem+0x131/0x270 htab_map_update_elem+0x50f/0xa80 bpf_fd_htab_map_update_elem+0x131/0x270 bpf_map_update_value+0x266/0x380 __sys_bpf+0x21bb/0x36b0 __x64_sys_bpf+0x45/0x60 x64_sys_call+0x1b2a/0x20d0 do_syscall_64+0x5d/0x100 entry_SYSCALL_64_after_hwframe+0x76/0x7e Una forma de corregir la advertencia de lockdep es usar raw_spinlock_t también para map_idr_lock. Sin embargo, bpf_map_alloc_id() invoca idr_alloc_cyclic() después de adquirir map_idr_lock, activará una advertencia de lockdep similar porque el bloqueo del slab (s->cpu_slab->lock) sigue siendo un spinlock. En lugar de cambiar el tipo de map_idr_lock, solucione el problema invocando htab_put_fd_value() después de htab_unlock_bucket(). Sin embargo, solo aplazar la invocación de htab_put_fd_value() no es suficiente, porque los punteros de mapa antiguos en htab de mapas no se pueden guardar durante la eliminación por lotes. Por lo tanto, también aplace la invocación de free_htab_elem(), para que estos elementos a liberar se puedan vincular entre sí de forma similar a lru map. Hay cuatro invocadores para ->map_fd_put_ptr: (1) alloc_htab_elem() (a través de htab_put_fd_value()) Invoca ->map_fd_put_ptr() bajo un raw_spinlock_t. La invocación de htab_put_fd_value() no se puede mover simplemente después de htab_unlock_bucket(), porque el elemento antiguo ya se ha almacenado en htab->extra_elems. Se puede reutilizar inmediatamente después de htab_unlock_bucket() y la invocación de htab_put_fd_value() después de htab_unlock_bucket() puede liberar el elemento recién agregado de manera incorrecta. Por lo tanto, se guarda el puntero del mapa del elemento antiguo para htab de mapas antes de desbloquear el depósito y se libera map_ptr después del desbloqueo. Además del puntero del mapa en el elemento antiguo, se debe hacer lo mismo para los campos especiales en el elemento antiguo también. (2) free_htab_elem() (a través de htab_put_fd_value()) Su llamador incluye __htab_map_lookup_and_delete_elem(), htab_map_delete_elem() y __htab_map_lookup_and_delete_batch(). Para htab_map_delete_elem(), simplemente invoque free_htab_elem() después de htab_unlock_bucket(). Para __htab_map_lookup_and_delete_batch(), al igual que lru map, vinculando el elemento a liberar en la lista node_to_free e invocando free_htab_elem() para estos elementos después del desbloqueo. Es seguro reutilizar batch_flink como el enlace para node_to_free, ---truncado---

Productos y versiones vulnerables

CPE Desde Hasta
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.13 (incluyendo) 6.6.66 (excluyendo)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.7 (incluyendo) 6.12.5 (excluyendo)