pola-rs/polars · error

could not execute mprotect for CPUID check

Error message

could not execute mprotect for CPUID check

What it means

On POSIX, polars writes a CPUID stub into an anonymous RW mmap and then calls mprotect to switch it to PROT_READ|PROT_EXEC before executing it at import time (write-then-protect to satisfy W^X-friendly platforms). This RuntimeError means mprotect returned non-zero: the kernel or a security policy refused to make the page executable, so the CPU feature probe cannot run.

Source

Thrown at py-polars/src/polars/_cpu_check.py:199

            # On some platforms PROT_WRITE + PROT_EXEC is forbidden, so we first
            # only write and then mprotect into PROT_EXEC.
            libc = _open_posix_libc()
            mprotect = libc.mprotect
            mprotect.argtypes = (ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int)
            mprotect.restype = ctypes.c_int

            self.mmap = mmap.mmap(
                -1,
                size,
                mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS,
                mmap.PROT_READ | mmap.PROT_WRITE,
            )
            self.addr = ctypes.addressof(ctypes.c_void_p.from_buffer(self.mmap))
            self.mmap.write(code)

            if mprotect(self.addr, size, mmap.PROT_READ | mmap.PROT_EXEC) != 0:
                msg = "could not execute mprotect for CPUID check"
                raise RuntimeError(msg)

        func_type = CFUNCTYPE(None, POINTER(CPUID_struct), c_uint32, c_uint32)
        self.func_ptr = func_type(self.addr)

    def __call__(self, eax: int, ecx: int = 0) -> CPUID_struct:
        struct = CPUID_struct()
        self.func_ptr(struct, eax, ecx)
        return struct

    def __del__(self) -> None:
        if _IS_WINDOWS:
            self.win.VirtualFree.restype = c_long
            self.win.VirtualFree.argtypes = [c_void_p, c_size_t, c_ulong]
            self.win.VirtualFree(self.addr, 0, _MEM_RELEASE)


def _read_cpu_flags() -> dict[str, bool]:
    if not _SUPPORTS_CPUID:

View on GitHub (pinned to df599052da)

Solutions

  1. Set `POLARS_SKIP_CPU_CHECK=1` in the environment before importing polars — the CPUID probe is skipped entirely and no executable mapping is created
  2. On OpenBSD, ensure the filesystem hosting site-packages (or /tmp) is mounted with the `wxallowed` option
  3. Relax the seccomp/AppArmor/PaX policy so the Python process may mprotect a private anonymous mapping to PROT_EXEC
  4. Run under a container/runtime profile that permits W->X transitions (default Docker seccomp profile does)

Example fix

# before
import polars as pl  # RuntimeError: could not execute mprotect for CPUID check

# after
import os
os.environ["POLARS_SKIP_CPU_CHECK"] = "1"
import polars as pl
Defensive patterns

Strategy: fallback

Validate before calling

import os, sys

if sys.platform != "win32" and os.environ.get("POLARS_SKIP_CPU_CHECK") is None:
    # hardened environments (PaX/OpenBSD wxallowed/seccomp W^X) can be detected cheaply:
    # if you know you run under one of these, skip the probe before importing polars
    hardened_markers = ["/proc/sys/kernel/grsecurity", "wxallowed-missing", "gvisor"]
    if any(os.path.exists(p) for p in hardened_markers[:1]):
        os.environ["POLARS_SKIP_CPU_CHECK"] = "1"

Try / catch

import sys
try:
    import polars as pl
except RuntimeError as e:
    if "CPUID" not in str(e):
        raise
    import os
    os.environ["POLARS_SKIP_CPU_CHECK"] = "1"
    for m in [m for m in sys.modules if m.startswith("polars")]:
        del sys.modules[m]
    import polars as pl  # noqa

Prevention

When it happens

Trigger: `import polars` on Linux/BSD under hardened kernels (PaX/grsec with MPROTECT), on OpenBSD when the filesystem backing the mapping is not mounted `wxallowed`, or inside sandboxes whose seccomp/AppArmor/gVisor profile rejects mprotect to PROT_EXEC.

Common situations: Hardened Gentoo/grsec hosts; OpenBSD default mounts; Docker with custom seccomp profiles denying exec-mprotect; endpoint-security software hooking mprotect; some minimal VM/emulation configurations.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/d9344cd087d73b5d. Report an issue: GitHub.