U.S. flag   An official website of the United States government
Dot gov

Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Https

Secure .gov websites use HTTPS
A lock (Dot gov) or https:// means you've safely connected to the .gov website. Share sensitive information only on official, secure websites.

Vulnerability Change Records for CVE-2026-23435

Change History

CVE Translated by NIST 7/21/2026 3:10:00 PM

Action Type Old Value New Value
Added Translation

                  
                
              
Title: Linux, Description: En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:

perf/x86: Mover la configuración del puntero de evento antes en x86_pmu_enable()

Un sistema AMD EPYC de producción falló con una desreferencia de puntero NULL en el gestor NMI de la PMU:

  BUG: desreferencia de puntero NULL del kernel, dirección: 0000000000000198
  RIP: x86_perf_event_update+0xc/0xa0
  Traza de Llamada:
   [NMI]
   amd_pmu_v2_handle_irq+0x1a6/0x390
   perf_event_nmi_handler+0x24/0x40

La instrucción que causó el fallo es 'cmpq $0x0, 0x198(%rdi)' con RDI=0, correspondiente a la comprobación 'if (unlikely(!hwc- event_base))' en x86_perf_event_update() donde hwc = &event- hw y event es NULL.

La inspección con drgn del vmcore en la CPU 106 mostró una discrepancia entre cpuc- active_mask y cpuc- events[]:

  active_mask: 0x1e (bits 1, 2, 3, 4)
  events[1]:   0xff1100136cbd4f38  (válido)
  events[2]:   0x0                 (NULL, pero el bit 2 de active_mask está activado)
  events[3]:   0xff1100076fd2cf38  (válido)
  events[4]:   0xff1100079e990a90  (válido)

El evento que debería ocupar events[2] se encontró en event_list[2] con hw.idx=2 y hw.state=0x0, confirmando que x86_pmu_start() se había ejecutado (lo que borra hw.state y establece active_mask) pero events[2] nunca fue poblado.

Otro evento (event_list[0]) tenía hw.state=0x7 (STOPPED|UPTODATE|ARCH), mostrando que se detuvo cuando la PMU reprogramó los eventos, confirmando que la secuencia de estrangulamiento y luego reprogramación ocurrió.

La causa raíz es el commit 7e772a93eb61 ( perf/x86: Solucionar acceso a evento NULL y posible pérdida de registro PEBS ) que movió la asignación de cpuc- events[idx] fuera de x86_pmu_start() y al paso 2 de x86_pmu_enable(), después de la comprobación PERF_HES_ARCH. Esto rompió cualquier ruta que llama a pmu- start() sin pasar por x86_pmu_enable() -- específicamente la ruta de desestrangulamiento:

  perf_adjust_freq_unthr_events()
    -  perf_event_unthrottle_group()
      -  perf_event_unthrottle()
        -  event- pmu- start(event, 0)
          -  x86_pmu_start()     // establece active_mask pero no events[]

La secuencia de la condición de carrera es:

  1. Un grupo de eventos perf desborda, lo que activa el estrangulamiento del grupo a través de perf_event_throttle_group(). Todos los eventos se detienen: los bits de active_mask se borran, events[] se preserva (x86_pmu_stop ya no borra events[] después del commit 7e772a93eb61).

  2. Mientras aún está estrangulado (PERF_HES_STOPPED), x86_pmu_enable() se ejecuta debido a otra actividad de planificación. Los eventos detenidos que necesitan mover contadores obtienen PERF_HES_ARCH establecido y events[old_idx] borrado. En el paso 2 de x86_pmu_enable(), PERF_HES_ARCH hace que estos eventos se omitan -- events[new_idx] nunca se establece.

  3. El tick del temporizador desestrángula el grupo a través de pmu- start(). Dado que el commit 7e772a93eb61 eliminó la asignación de events[] de x86_pmu_start(), active_mask[new_idx] se establece pero events[new_idx] permanece NULL.

  4. Se dispara una NMI de desbordamiento de PMC. El gestor itera los contadores activos, encuentra active_mask[2] establecido, lee events[2] que es NULL, y falla al desreferenciarlo.

Mover la asignación de cpuc- events[hwc- idx] en x86_pmu_enable() a antes de la comprobación PERF_HES_ARCH, para que events[] se pueble incluso para eventos que no se inician inmediatamente. Esto asegura que la ruta de desestrangulamiento a través de pmu- start() siempre encuentre un puntero de evento válido.