CVE-2024-53058

In the Linux kernel, the following vulnerability has been resolved: net: stmmac: TSO: Fix unbalanced DMA map/unmap for non-paged SKB data In case the non-paged data of a SKB carries protocol header and protocol payload to be transmitted on a certain platform that the DMA AXI address width is configured to 40-bit/48-bit, or the size of the non-paged data is bigger than TSO_MAX_BUFF_SIZE on a certain platform that the DMA AXI address width is configured to 32-bit, then this SKB requires at least two DMA transmit descriptors to serve it. For example, three descriptors are allocated to split one DMA buffer mapped from one piece of non-paged data: dma_desc[N + 0], dma_desc[N + 1], dma_desc[N + 2]. Then three elements of tx_q->tx_skbuff_dma[] will be allocated to hold extra information to be reused in stmmac_tx_clean(): tx_q->tx_skbuff_dma[N + 0], tx_q->tx_skbuff_dma[N + 1], tx_q->tx_skbuff_dma[N + 2]. Now we focus on tx_q->tx_skbuff_dma[entry].buf, which is the DMA buffer address returned by DMA mapping call. stmmac_tx_clean() will try to unmap the DMA buffer _ONLY_IF_ tx_q->tx_skbuff_dma[entry].buf is a valid buffer address. The expected behavior that saves DMA buffer address of this non-paged data to tx_q->tx_skbuff_dma[entry].buf is: tx_q->tx_skbuff_dma[N + 0].buf = NULL; tx_q->tx_skbuff_dma[N + 1].buf = NULL; tx_q->tx_skbuff_dma[N + 2].buf = dma_map_single(); Unfortunately, the current code misbehaves like this: tx_q->tx_skbuff_dma[N + 0].buf = dma_map_single(); tx_q->tx_skbuff_dma[N + 1].buf = NULL; tx_q->tx_skbuff_dma[N + 2].buf = NULL; On the stmmac_tx_clean() side, when dma_desc[N + 0] is closed by the DMA engine, tx_q->tx_skbuff_dma[N + 0].buf is a valid buffer address obviously, then the DMA buffer will be unmapped immediately. There may be a rare case that the DMA engine does not finish the pending dma_desc[N + 1], dma_desc[N + 2] yet. Now things will go horribly wrong, DMA is going to access a unmapped/unreferenced memory region, corrupted data will be transmited or iommu fault will be triggered :( In contrast, the for-loop that maps SKB fragments behaves perfectly as expected, and that is how the driver should do for both non-paged data and paged frags actually. This patch corrects DMA map/unmap sequences by fixing the array index for tx_q->tx_skbuff_dma[entry].buf when assigning DMA buffer address. Tested and verified on DWXGMAC CORE 3.20a
Configurations

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc5:*:*:*:*:*:*

History

22 Nov 2024, 17:53

Type Values Removed Values Added
CVSS v2 : unknown
v3 : unknown
v2 : unknown
v3 : 5.5
References () https://git.kernel.org/stable/c/07c9c26e37542486e34d767505e842f48f29c3f6 - () https://git.kernel.org/stable/c/07c9c26e37542486e34d767505e842f48f29c3f6 - Patch
References () https://git.kernel.org/stable/c/58d23d835eb498336716cca55b5714191a309286 - () https://git.kernel.org/stable/c/58d23d835eb498336716cca55b5714191a309286 - Patch
References () https://git.kernel.org/stable/c/66600fac7a984dea4ae095411f644770b2561ede - () https://git.kernel.org/stable/c/66600fac7a984dea4ae095411f644770b2561ede - Patch
References () https://git.kernel.org/stable/c/a3ff23f7c3f0e13f718900803e090fd3997d6bc9 - () https://git.kernel.org/stable/c/a3ff23f7c3f0e13f718900803e090fd3997d6bc9 - Patch
References () https://git.kernel.org/stable/c/ece593fc9c00741b682869d3f3dc584d37b7c9df - () https://git.kernel.org/stable/c/ece593fc9c00741b682869d3f3dc584d37b7c9df - Patch
Summary
  • (es) En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: net: stmmac: TSO: Fix DMA map/unmap no balanceado para datos SKB no paginados En caso de que los datos no paginados de un SKB lleven encabezado de protocolo y payload de protocolo para ser transmitidos en una determinada plataforma que el ancho de dirección DMA AXI está configurado a 40 bits/48 bits, o el tamaño de los datos no paginados es mayor que TSO_MAX_BUFF_SIZE en una determinada plataforma que el ancho de dirección DMA AXI está configurado a 32 bits, entonces este SKB requiere al menos dos descriptores de transmisión DMA para servirlo. Por ejemplo, se asignan tres descriptores para dividir un buffer DMA mapeado a partir de una pieza de datos no paginados: dma_desc[N + 0], dma_desc[N + 1], dma_desc[N + 2]. Luego, se asignarán tres elementos de tx_q->tx_skbuff_dma[] para almacenar información adicional que se reutilizará en stmmac_tx_clean(): tx_q->tx_skbuff_dma[N + 0], tx_q->tx_skbuff_dma[N + 1], tx_q->tx_skbuff_dma[N + 2]. Ahora nos centramos en tx_q->tx_skbuff_dma[entry].buf, que es la dirección del búfer DMA devuelta por la llamada de mapeo DMA. stmmac_tx_clean() intentará desasignar el búfer DMA _SOLO_SI_ tx_q->tx_skbuff_dma[entry].buf es una dirección de búfer válida. El comportamiento esperado que guarda la dirección del buffer DMA de estos datos no paginados en tx_q->tx_skbuff_dma[entrada].buf es: tx_q->tx_skbuff_dma[N + 0].buf = NULL; tx_q->tx_skbuff_dma[N + 1].buf = NULL; tx_q->tx_skbuff_dma[N + 2].buf = dma_map_single(); Desafortunadamente, el código actual se comporta mal de esta manera: tx_q->tx_skbuff_dma[N + 0].buf = dma_map_single(); tx_q->tx_skbuff_dma[N + 1].buf = NULL; tx_q->tx_skbuff_dma[N + 2].buf = NULL; En el lado stmmac_tx_clean(), cuando el motor DMA cierra dma_desc[N + 0], tx_q->tx_skbuff_dma[N + 0].buf es obviamente una dirección de búfer válida, entonces el búfer DMA se desasignará inmediatamente. Puede haber un caso poco común en el que el motor DMA no finalice aún los dma_desc[N + 1], dma_desc[N + 2] pendientes. Ahora las cosas saldrán terriblemente mal, DMA accederá a una región de memoria no mapeada/no referenciada, se transmitirán datos corruptos o se activará un error de iommu :( Por el contrario, el bucle for que mapea fragmentos SKB se comporta perfectamente como se espera, y así es como el controlador debería funcionar tanto para datos no paginados como para fragmentos paginados en realidad. Este parche corrige las secuencias de mapeo/desasignamiento de DMA al arreglar el índice de matriz para tx_q->tx_skbuff_dma[entry].buf al asignar la dirección del búfer de DMA. Probado y verificado en DWXGMAC CORE 3.20a
CPE cpe:2.3:o:linux:linux_kernel:6.12:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
CWE NVD-CWE-noinfo
First Time Linux linux Kernel
Linux

19 Nov 2024, 18:15

Type Values Removed Values Added
New CVE

Information

Published : 2024-11-19 18:15

Updated : 2024-11-22 17:53


NVD link : CVE-2024-53058

Mitre link : CVE-2024-53058

CVE.ORG link : CVE-2024-53058


JSON object : View

Products Affected

linux

  • linux_kernel