Skip to content

[BUG] Use-after-free: spi dereferenced after free() in psutil_cpu_stats (Windows) #2847

Description

@Fuyugithub

Bug Description

In psutil/arch/windows/cpu.c, the psutil_cpu_stats function frees the spi pointer on line 331, but then dereferences it on lines 336 and 339 within the Py_BuildValue call.

Location

psutil/arch/windows/cpu.c:331-340

Code

free(spi);           // line 331: spi freed here
free(InterruptInformation);
free(sppi);
return Py_BuildValue(
    "kkkk",
    spi->ContextSwitches,   // line 336: USE AFTER FREE
    interrupts,
    (unsigned long)dpcs,
    spi->SystemCalls         // line 339: USE AFTER FREE
);

Impact

After free(spi), the memory pointed to by spi may be reused by another allocation or overwritten by another thread. Reading spi->ContextSwitches and spi->SystemCalls after the free is undefined behavior that can produce:

  • Incorrect/garbage values returned to Python
  • Crash (SIGSEGV) if the page is unmapped
  • Security risk if the freed memory is reused with attacker-controlled data

This affects every call to psutil.cpu_stats() on Windows.

Suggested Fix

Save the values into local variables before freeing:

unsigned long ctx_switches = spi->ContextSwitches;
unsigned long syscalls = spi->SystemCalls;
free(spi);
free(InterruptInformation);
free(sppi);
return Py_BuildValue("kkkk", ctx_switches, interrupts, (unsigned long)dpcs, syscalls);

Environment

  • OS: Windows (all versions)
  • psutil version: current main (commit 7b6a9a6)
  • Affected API: psutil.cpu_stats()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions