« Volver al listado

CVE-2025-21693

Estado: ModificadaAlta (7.8)—

In the Linux kernel, the following vulnerability has been resolved:

mm: zswap: properly synchronize freeing resources during CPU hotunplug

In zswap_compress() and zswap_decompress(), the per-CPU acomp_ctx of the current CPU at the beginning of the operation is retrieved and used throughout. However, since neither preemption nor migration are disabled, it is possible that the operation continues on a different CPU.

If the original CPU is hotunplugged while the acomp_ctx is still in use, we run into a UAF bug as some of the resources attached to the acomp_ctx are freed during hotunplug in zswap_cpu_comp_dead() (i.e. acomp_ctx.buffer, acomp_ctx.req, or acomp_ctx.acomp).

Leer descripción completaMostrar menos

The problem was introduced in commit 1ec3b5fe6eec ("mm/zswap: move to use crypto_acomp API for hardware acceleration") when the switch to the crypto_acomp API was made. Prior to that, the per-CPU crypto_comp was retrieved using get_cpu_ptr() which disables preemption and makes sure the CPU cannot go away from under us. Preemption cannot be disabled with the crypto_acomp API as a sleepable context is needed.

Use the acomp_ctx.mutex to synchronize CPU hotplug callbacks allocating and freeing resources with compression/decompression paths. Make sure that acomp_ctx.req is NULL when the resources are freed. In the compression/decompression paths, check if acomp_ctx.req is NULL after acquiring the mutex (meaning the CPU was offlined) and retry on the new CPU.

The initialization of acomp_ctx.mutex is moved from the CPU hotplug callback to the pool initialization where it belongs (where the mutex is allocated). In addition to adding clarity, this makes sure that CPU hotplug cannot reinitialize a mutex that is already locked by compression/decompression.

Previously a fix was attempted by holding cpus_read_lock() [1]. This would have caused a potential deadlock as it is possible for code already holding the lock to fall into reclaim and enter zswap (causing a deadlock). A fix was also attempted using SRCU for synchronization, but Johannes pointed out that synchronize_srcu() cannot be used in CPU hotplug notifiers [2].

[1]https://lkml.kernel.org/20241219212437.2714151-1-yosryahmed@google.com/ [2]https://lkml.kernel.org/20250107074724.1756696-2-yosryahmed@google.com/ [3]https://lkml.kernel.org/20250107222236.2715883-2-yosryahmed@google.com/

[yosryahmed@google.com: remove comment]

Detalles técnicos trazas, registros y código del informe original
Alternative fixes that were considered/attempted and could have worked:
- Refcounting the per-CPU acomp_ctx. This involves complexity in
  handling the race between the refcount dropping to zero in
  zswap_[de]compress() and the refcount being re-initialized when the
  CPU is onlined.
- Disabling migration before getting the per-CPU acomp_ctx [3], but
  that's discouraged and is a much bigger hammer than needed, and could
  result in subtle performance issues.

CVSS

Probabilidad de explotación (EPSS)

EPSS (Exploit Prediction Scoring System, de FIRST) estima la probabilidad de que una vulnerabilidad sea explotada en 30 días. Complementa a CVSS (impacto) y a CISA KEV (explotación confirmada).

🎯 Técnicas ATT&CK

Cómo se explota esta vulnerabilidad y qué consigue el atacante, en el lenguaje de MITRE ATT&CK.

UAF en kernel Linux (CWE-416) con acceso local y privilegios mínimos (PR:L) permite escalada a ejecución de código o DoS. Vector AV:L/PR:L/UI:N dicta T1068; el UAF puede llevar a ejecución arbitraria (T1059) o bloqueo del sistema.

Inferido por nuestro agente de análisis a partir de la descripción oficial, el vector CVSS y la CWE, y comprobado por un supervisor. Puede contener errores.

🛡️ Mitigaciones ATT&CK que cubren estas técnicas

Tecnologías afectadas (1)

CWE

Referencias

JSON original (NVD)

Mostrar
{
  "id": "CVE-2025-21693",
  "cveTags": [],
  "metrics": {
    "ssvcV203": [
      {
        "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
        "ssvcData": {
          "id": "CVE-2025-21693",
          "role": "CISA Coordinator",
          "options": [
            {
              "exploitation": "none"
            },
            {
              "automatable": "no"
            },
            {
              "technicalImpact": "total"
            }
          ],
          "version": "2.0.3",
          "timestamp": "2025-02-10T17:10:07.856772Z"
        }
      }
    ],
    "cvssMetricV31": [
      {
        "type": "Secondary",
        "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
        "cvssData": {
          "scope": "UNCHANGED",
          "version": "3.1",
          "baseScore": 7.8,
          "attackVector": "LOCAL",
          "baseSeverity": "HIGH",
          "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
          "integrityImpact": "HIGH",
          "userInteraction": "NONE",
          "attackComplexity": "LOW",
          "availabilityImpact": "HIGH",
          "privilegesRequired": "LOW",
          "confidentialityImpact": "HIGH"
        },
        "impactScore": 5.9,
        "exploitabilityScore": 1.8
      }
    ]
  },
  "affected": [
    {
      "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
      "affectedData": [
        {
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "product": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "1ec3b5fe6eec782f4e5e0a80e4ce1909ffd5d161",
              "lessThan": "8d29ff5d50304daa41dc3cfdda4a9d1e46cf5be1",
              "versionType": "git"
            },
            {
              "status": "affected",
              "version": "1ec3b5fe6eec782f4e5e0a80e4ce1909ffd5d161",
              "lessThan": "12dcb0ef540629a281533f9dedc1b6b8e14cfb65",
              "versionType": "git"
            }
          ],
          "programFiles": [
            "mm/zswap.c"
          ],
          "defaultStatus": "unaffected"
        },
        {
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "product": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "5.11"
            },
            {
              "status": "unaffected",
              "version": "0",
              "lessThan": "5.11",
              "versionType": "semver"
            },
            {
              "status": "unaffected",
              "version": "6.12.12",
              "versionType": "semver",
              "lessThanOrEqual": "6.12.*"
            },
            {
              "status": "unaffected",
              "version": "6.13",
              "versionType": "original_commit_for_fix",
              "lessThanOrEqual": "*"
            }
          ],
          "programFiles": [
            "mm/zswap.c"
          ],
          "defaultStatus": "affected"
        }
      ]
    }
  ],
  "published": "2025-02-10T16:15:38.883",
  "references": [
    {
      "url": "https://git.kernel.org/stable/c/12dcb0ef540629a281533f9dedc1b6b8e14cfb65",
      "tags": [
        "Patch"
      ],
      "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
    },
    {
      "url": "https://git.kernel.org/stable/c/8d29ff5d50304daa41dc3cfdda4a9d1e46cf5be1",
      "tags": [
        "Patch"
      ],
      "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
    }
  ],
  "vulnStatus": "Modified",
  "weaknesses": [
    {
      "type": "Secondary",
      "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
      "description": [
        {
          "lang": "en",
          "value": "CWE-416"
        }
      ]
    }
  ],
  "descriptions": [
    {
      "lang": "en",
      "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm: zswap: properly synchronize freeing resources during CPU hotunplug\n\nIn zswap_compress() and zswap_decompress(), the per-CPU acomp_ctx of the\ncurrent CPU at the beginning of the operation is retrieved and used\nthroughout.  However, since neither preemption nor migration are disabled,\nit is possible that the operation continues on a different CPU.\n\nIf the original CPU is hotunplugged while the acomp_ctx is still in use,\nwe run into a UAF bug as some of the resources attached to the acomp_ctx\nare freed during hotunplug in zswap_cpu_comp_dead() (i.e. \nacomp_ctx.buffer, acomp_ctx.req, or acomp_ctx.acomp).\n\nThe problem was introduced in commit 1ec3b5fe6eec (\"mm/zswap: move to use\ncrypto_acomp API for hardware acceleration\") when the switch to the\ncrypto_acomp API was made.  Prior to that, the per-CPU crypto_comp was\nretrieved using get_cpu_ptr() which disables preemption and makes sure the\nCPU cannot go away from under us.  Preemption cannot be disabled with the\ncrypto_acomp API as a sleepable context is needed.\n\nUse the acomp_ctx.mutex to synchronize CPU hotplug callbacks allocating\nand freeing resources with compression/decompression paths.  Make sure\nthat acomp_ctx.req is NULL when the resources are freed.  In the\ncompression/decompression paths, check if acomp_ctx.req is NULL after\nacquiring the mutex (meaning the CPU was offlined) and retry on the new\nCPU.\n\nThe initialization of acomp_ctx.mutex is moved from the CPU hotplug\ncallback to the pool initialization where it belongs (where the mutex is\nallocated).  In addition to adding clarity, this makes sure that CPU\nhotplug cannot reinitialize a mutex that is already locked by\ncompression/decompression.\n\nPreviously a fix was attempted by holding cpus_read_lock() [1].  This\nwould have caused a potential deadlock as it is possible for code already\nholding the lock to fall into reclaim and enter zswap (causing a\ndeadlock).  A fix was also attempted using SRCU for synchronization, but\nJohannes pointed out that synchronize_srcu() cannot be used in CPU hotplug\nnotifiers [2].\n\nAlternative fixes that were considered/attempted and could have worked:\n- Refcounting the per-CPU acomp_ctx. This involves complexity in\n  handling the race between the refcount dropping to zero in\n  zswap_[de]compress() and the refcount being re-initialized when the\n  CPU is onlined.\n- Disabling migration before getting the per-CPU acomp_ctx [3], but\n  that's discouraged and is a much bigger hammer than needed, and could\n  result in subtle performance issues.\n\n[1]https://lkml.kernel.org/20241219212437.2714151-1-yosryahmed@google.com/\n[2]https://lkml.kernel.org/20250107074724.1756696-2-yosryahmed@google.com/\n[3]https://lkml.kernel.org/20250107222236.2715883-2-yosryahmed@google.com/\n\n[yosryahmed@google.com: remove comment]"
    },
    {
      "lang": "es",
      "value": "En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: mm: zswap: sincronizar correctamente la liberación de recursos durante la desconexión en caliente de la CPU En zswap_compress() y zswap_decompress(), se recupera y se utiliza en todo momento el acomp_ctx por CPU de la CPU actual al comienzo de la operación. Sin embargo, dado que ni la preempción ni la migración están deshabilitadas, es posible que la operación continúe en una CPU diferente. Si se desconecta en caliente la CPU original mientras el acomp_ctx todavía está en uso, nos encontramos con un error de UAF ya que algunos de los recursos adjuntos al acomp_ctx se liberan durante la desconexión en caliente en zswap_cpu_comp_dead() (es decir, acomp_ctx.buffer, acomp_ctx.req o acomp_ctx.acomp). El problema se introdujo en el commit 1ec3b5fe6eec (\"mm/zswap: pasar a usar la API crypto_acomp para la aceleración de hardware\") cuando se realizó el cambio a la API crypto_acomp. Antes de eso, el crypto_comp por CPU se recuperaba usando get_cpu_ptr() que deshabilita la preempción y se asegura de que la CPU no pueda irse de debajo de nosotros. La preempción no se puede deshabilitar con la API crypto_acomp ya que se necesita un contexto inactivo. Use acomp_ctx.mutex para sincronizar las devoluciones de llamadas hotplug de la CPU que asignan y liberan recursos con rutas de compresión/descompresión. Asegúrese de que acomp_ctx.req sea NULL cuando se liberan los recursos. En las rutas de compresión/descompresión, verifique si acomp_ctx.req es NULL después de adquirir el mutex (lo que significa que la CPU estaba fuera de línea) y vuelva a intentarlo en la nueva CPU. La inicialización de acomp_ctx.mutex se mueve de la devolución de llamada hotplug de la CPU a la inicialización del grupo donde pertenece (donde se asigna el mutex). Además de agregar claridad, esto asegura que la conexión en caliente de la CPU no pueda reinicializar un mutex que ya está bloqueado por compresión/descompresión. Anteriormente se intentó una solución manteniendo pulsada la tecla cpus_read_lock() [1]. Esto habría provocado un posible bloqueo, ya que es posible que el código que ya mantiene el bloqueo caiga en recuperación y entre en zswap (provocando un bloqueo). También se intentó una solución utilizando SRCU para la sincronización, pero Johannes señaló que no se puede utilizarsynchronous_srcu() en los notificadores de conexión en caliente de la CPU [2]. Workarounds que se consideraron/intentaron y que podrían haber funcionado: - Refcounting el acomp_ctx por CPU. Esto implica complejidad en la gestión de la ejecución entre el refcount que cae a cero en zswap_[de]compress() y el refcount que se reinicializa cuando la CPU está en línea. - Deshabilitar la migración antes de obtener el acomp_ctx por CPU [3], pero eso no se recomienda y es un martillo mucho más grande de lo necesario, y podría dar lugar a problemas de rendimiento sutiles. [1]https://lkml.kernel.org/20241219212437.2714151-1-yosryahmed@google.com/ [2]https://lkml.kernel.org/20250107074724.1756696-2-yosryahmed@google.com/ [3]https://lkml.kernel.org/20250107222236.2715883-2-yosryahmed@google.com/ [yosryahmed@google.com: eliminar comentario] Enlace: https://lkml.kernel.org/r/CAJD7tkaxS1wjn+swugt8QCvQ-rVF5RZnjxwPGX17k8x9zSManA@mail.gmail.com"
    }
  ],
  "lastModified": "2026-06-17T08:44:02.480",
  "configurations": [
    {
      "nodes": [
        {
          "negate": false,
          "cpeMatch": [
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "1E1E1BB4-D8B4-4864-84DE-04926804B5EF",
              "versionEndExcluding": "6.12.12",
              "versionStartIncluding": "5.11"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc1:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "62567B3C-6CEE-46D0-BC2E-B3717FBF7D13"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc2:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "5A073481-106D-4B15-B4C7-FB0213B8E1D4"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc3:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "DE491969-75AE-4A6B-9A58-8FC5AF98798F"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc4:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "93C0660D-7FB8-4FBA-892A-B064BA71E49E"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc5:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "034C36A6-C481-41F3-AE9A-D116E5BE6895"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc6:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "8AF9DC49-2085-4FFB-A7E3-73DFAFECC7F2"
            },
            {
              "criteria": "cpe:2.3:o:linux:linux_kernel:6.13:rc7:*:*:*:*:*:*",
              "vulnerable": true,
              "matchCriteriaId": "5DFCDFB8-4FD0-465A-9076-D813D78FE51B"
            }
          ],
          "operator": "OR"
        }
      ]
    }
  ],
  "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}