In the Linux kernel, the following vulnerability has been resolved: dm thin: make get_first_thin use rcu-safe list first function The documentation in rculist.h explains the absence of list_empty_rcu() and cautions programmers against relying on a list_empty() -> list_first() sequence in RCU safe code. This is because each of these functions performs its own READ_ONCE() of the list head. This can lead to a situation where the list_empty() sees a valid list entry, but the subsequent list_first() sees a different view of list head state after a modification. In the case of dm-thin, this author had a production box crash from a GP fault in the process_deferred_bios path. This function saw a valid list head in get_first_thin() but when it subsequently dereferenced that and turned it into a thin_c, it got the inside of the struct pool, since the list was now empty and referring to itself. The kernel on which this occurred printed both a warning about a refcount_t being saturated, and a UBSAN error for an out-of-bounds cpuid access in the queued spinlock, prior to the fault itself. When the resulting kdump was examined, it was possible to see another thread patiently waiting in thin_dtr's synchronize_rcu. The thin_dtr call managed to pull the thin_c out of the active thins list (and have it be the last entry in the active_thins list) at just the wrong moment which lead to this crash. Fortunately, the fix here is straight forward. Switch get_first_thin() function to use list_first_or_null_rcu() which performs just a single READ_ONCE() and returns NULL if the list is already empty. This was run against the devicemapper test suite's thin-provisioning suites for delete and suspend and no regressions were observed.
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: dm thin: hacer que get_first_thin use la función list first de rcu-safe La documentación en rculist.h explica la ausencia de list_empty_rcu() y advierte a los programadores que no confíen en una secuencia list_empty() -> list_first() en el código seguro de RCU. Esto se debe a que cada una de estas funciones realiza su propio READ_ONCE() del encabezado de la lista. Esto puede llevar a una situación en la que list_empty() ve una entrada de lista válida, pero el list_first() posterior ve una vista diferente del estado del encabezado de lista después de una modificación. En el caso de dm-thin, este autor tuvo un bloqueo del cuadro de producción debido a una falla de GP en la ruta process_deferred_bios. Esta función vio un encabezado de lista válido en get_first_thin() pero cuando posteriormente desreferenciaba eso y lo convertía en un thin_c, obtuvo el interior del grupo de estructuras, ya que la lista ahora estaba vacía y se refería a sí misma. El núcleo en el que esto ocurrió imprimió una advertencia sobre la saturación de un refcount_t y un error UBSAN por un acceso a cpuid fuera de los límites en el spinlock en cola, antes del fallo en sí. Cuando se examinó el kdump resultante, fue posible ver otro hilo esperando pacientemente en elsynchronous_rcu de thin_dtr. La llamada thin_dtr logró sacar el thin_c de la lista de thins activa (y hacer que sea la última entrada en la lista de active_thins) justo en el momento equivocado, lo que provocó este bloqueo. Afortunadamente, la solución aquí es sencilla. Cambie la función get_first_thin() para usar list_first_or_null_rcu() que realiza solo un único READ_ONCE() y devuelve NULL si la lista ya está vacía. Esto se ejecutó contra las suites de aprovisionamiento fino del conjunto de pruebas devicemapper para eliminar y suspender y no se observaron regresiones.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
| Attack Vector | LOCAL |
|---|---|
| Attack Complexity | LOW |
| Privileges Required | LOW |
| User Interaction | NONE |
| Scope | UNCHANGED |
| Confidentiality Impact | NONE |
| Integrity Impact | NONE |
| Availability Impact | HIGH |
| Source | Type | Description |
|---|---|---|
| [email protected] | Primary |
en
NVD-CWE-noinfo
|
| Vendor | Product | Version | Update | Type |
|---|---|---|---|---|
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd36be7af00> | Operating System |
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd36be79e80> | Operating System |
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd34b8dbb00> | Operating System |
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd340ad4040> | Operating System |
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd36be7b340> | Operating System |
| linux | linux_kernel | * | <built-in method update of dict object at 0x7fd36be789c0> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd340ad7740> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd34b8db640> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd340ad5a00> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd36be79080> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd34b8dac40> | Operating System |
| linux | linux_kernel | 3.15 | <built-in method update of dict object at 0x7fd36be78f80> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd384a9b880> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd384aa9b80> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd34b8dbc40> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd340ad4240> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd36be78dc0> | Operating System |
| linux | linux_kernel | 6.13 | <built-in method update of dict object at 0x7fd340ad5fc0> | Operating System |
| Vulnerable | CPE |
|---|---|
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:-:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:rc4:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:rc5:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:rc6:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:rc7:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:3.15:rc8:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc1:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc2:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc3:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc4:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc5:*:*:*:*:*:* |
| Yes | cpe:2.3:o:linux:linux_kernel:6.13:rc6:*:*:*:*:*:* |