← All rules
SOCLE-CLD-KRN-047// Kernel buildmediumeffective runtime

Disable vsyscall emulate execution only

Requires the kernel to be built without CONFIG_LEGACY_VSYSCALL_XONLY=y, favoring full removal via NONE instead of an execute-only vsyscall page.

Checked against the resolved running state (e.g. sshd -T, sysctl, systemctl show), catches drop-ins and Includes a file read would miss. Caveat: runtime ≠ persistence; a value correct now may not survive a reboot.

A pass proves✓ running now✓ on disk✓ survives rebootthe qualified verdict →
Debian 12CIS 1.1.0Debian 13CIS 1.0.0FedoraRHEL 10 / Rocky 10 / AlmaLinux 10RHEL 9 / Rocky 9 / AlmaLinux 9CIS 2.0.0Ubuntu 22.04CIS 3.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04
One check, maps to 1 standard

Pavois asserts the effective configuration, the live, resolved state, not a file. File-based scanners (OVAL/SCAP, Lynis) miss Includes, drop-ins and runtime defaults; this check sees what is actually applied.

A mapping is a cross-reference to where each standard places this requirement, anchored and cross-validated, not a claim of equivalence. A passing check is evidence toward these references, how to read it.

Why this rule matters

CONFIG_LEGACY_VSYSCALL_XONLY=y keeps the vsyscall page mapped execute-only at its fixed address: reads are blocked but the page is still present and executable. Because its address and contents are fixed, the executable bytes can still be used as ROP gadgets to bypass ASLR. XONLY is a hardening improvement over EMULATE but weaker than removing the page; the rule prefers NONE (no mapping at all), so it flags a kernel that only restricts vsyscall to execute-only.

What Pavois checks

Pavois reads the build configuration of the running kernel, /boot/config-$(uname -r) and the in-memory /proc/config.gz, and confirms CONFIG_LEGACY_VSYSCALL_XONLY is not set to y. vsyscall mode is a compile-time choice, so reading the booted kernel's real config (not a stale /boot/config-*) shows which variant is actually active.

describe command("C=/boot/config-$(uname -r); if [ -r \"$C\" ]; then cat \"$C\"; elif zcat /proc/config.gz 2>/dev/null | head -1 | grep -q .; then zcat /proc/config.gz; else echo PAVOIS_NO_KERNEL_CONFIG; fi | grep -E '^(CONFIG_LEGACY_VSYSCALL_XONLY=|PAVOIS_NO_KERNEL_CONFIG)'") do
  its('stdout') { should_not match(/PAVOIS_NO_KERNEL_CONFIG/) }
  its('stdout') { should_not match(/^CONFIG_LEGACY_VSYSCALL_XONLY=y$/) }
end

How to verify it is applied

Run grep '^CONFIG_LEGACY_VSYSCALL' /boot/config-$(uname -r). Expected: CONFIG_LEGACY_VSYSCALL_XONLY absent or is not set, with CONFIG_LEGACY_VSYSCALL_NONE=y selected instead.

Inspect & investigate

No dedicated log. The active vsyscall mode is influenced at boot via the vsyscall= parameter in cat /proc/cmdline. Blocked vsyscall reads surface as segfaults in dmesg | grep -i -e vsyscall -e segfault or journalctl -k | grep -i vsyscall.

Remediation

No automated remediation: this is a kernel build-time choice, not a runtime tunable. Pavois's harden plan is empty. To fix it you must boot a kernel built with CONFIG_LEGACY_VSYSCALL_NONE=y instead of xonly. At runtime you can fully disable the page on a still-mapping kernel with the vsyscall=none boot parameter, but the compile-time NONE choice this rule prefers requires a different kernel.

Pavois applies this with its own harden engine, the plan below, not a shell script:

resourcekernel_build
pavois harden plan local

where the target is local, a user@host SSH alias, or a container , Docs

Impact & precautions

Switching from XONLY to NONE removes the vsyscall page used as a compatibility shim by very old statically linked binaries (glibc older than ~2.14); modern software using the vDSO is unaffected. Audit for legacy static binaries before applying; if one is required, vsyscall=emulate is the (less-secure) compatibility fallback. Because the change requires a different kernel, keep the previous kernel entry in the bootloader.

Standards mapping

StandardReferenceTypeVersionConfidence
ANSSI BP-028R15direct2.0high

Each reference is a cross-reference anchored in the upstream benchmark and cross-validated against the SCAP Security Guide and ansible-lockdown, not a claim of equivalence. Direct = a prescriptive, line-level requirement; supporting = an abstract control family (NIST) the check provides evidence toward. How to read a mapping.

Sources & references

Official standards

ANSSI-BP-028 (2.0) ↗