KASLR Bypass Techniques
August 22, 2026 · View on GitHub
Survey of techniques a local process — typically unprivileged, but including paths that a container capability or a relaxed configuration unlocks — can use to recover the kernel text base or other layout secrets across mainstream Linux. This document indexes the entire technique space. Techniques KASLD implements are documented with a link to the component source; everything else points at the canonical reference.
KASLR bypass techniques broadly fall into several categories: reading kernel pointers or memory layout details from filesystem interfaces, exploiting microarchitectural or software side-channels, leaking addresses through syscalls and kernel interfaces, exploiting ioctl handlers that copy uninitialized kernel memory to userspace, brute-forcing memory layout constraints, taking advantage of weak randomization entropy, leveraging patched kernel info leak bugs, and leveraging exploit primitives.
Grouped by what a leak needs — from reading an interface, through measuring or inferring, to exploiting a bug:
Table of Contents
- Filesystem leaks
- Side-channels
- Syscall and interface leaks
- ioctl leaks
- Brute force
- Weak entropy
- Patched kernel bugs
- Exploit primitives
Filesystem leaks
The kernel exposes a variety of information through pseudo-filesystems
(/proc, /sys), log files (/var/log), and boot configuration files
(/boot, /proc/config.gz) that can reveal kernel pointers or memory
layout details to unprivileged users.
System logs
Kernel and system logs (dmesg / syslog) offer a wealth of information,
including kernel pointers and the layout of virtual and physical memory.
Many KASLD components search the kernel message ring buffer for kernel addresses.
The following KASLD components read from dmesg and /var/log/dmesg:
- dmesg_acpi_dynamic_ssdt.c
- dmesg_android_ion_snapshot.c
- dmesg_backtrace.c
- dmesg_check_for_initrd.c
- dmesg_cma_reserved.c
- dmesg_crashkernel.c
- dmesg_driver_component_ops.c
- dmesg_e820_memory_map.c
- dmesg_early_init_dt_add_memory_arch.c
- dmesg_efi_memmap.c
- dmesg_ex_handler_msr.c
- dmesg_fake_numa_init.c
- dmesg_free_area_init_node.c
- dmesg_free_reserved_area.c
- dmesg_kaslr_disabled.c
- dmesg_last_pfn.c
- dmesg_mem_init_kernel_layout.c
- dmesg_mmu_idmap.c
- dmesg_node_data.c
- dmesg_ramdisk.c
- dmesg_reserved_mem.c
- dmesg_reserved_mem_opensbi.c
- dmesg_riscv_relocation.c
- dmesg_swiotlb.c
Historically, raw kernel pointers were frequently printed to the system log
without using the %pK printk format.
Bugs which trigger a kernel oops can be used to leak kernel pointers by reading
the associated backtrace from system logs (on systems with kernel.panic_on_oops = 0).
For testing purposes, a backtrace can be forced using SysRq (requires root):
echo l > /proc/sysrq-trigger
This prints a backtrace of all CPUs to the kernel log, which the
dmesg_backtrace component will then parse. The SysRq l command requires
kernel.sysrq to include bit 4 (dump-backtrace), which is enabled by default
on most distro kernels (kernel.sysrq = 1 enables all commands).
Most modern distros ship with kernel.dmesg_restrict enabled by default to
prevent unprivileged users from accessing the kernel debug log. Similarly,
grsecurity hardened kernels support kernel.grsecurity.dmesg to prevent
unprivileged access.
System log files (i.e., /var/log/syslog) are readable only by privileged users
on modern distros. On Debian/Ubuntu systems, users in the adm group also have
read permissions on various system log files in /var/log/:
$ ls -la /var/log/syslog /var/log/kern.log /var/log/dmesg
-rw-r----- 1 root adm 147726 Jan 8 01:43 /var/log/dmesg
-rw-r----- 1 syslog adm 230 Jan 15 00:00 /var/log/kern.log
-rw-r----- 1 syslog adm 8322 Jan 15 04:26 /var/log/syslog
Typically the first user created during installation of an Ubuntu system
is a member of the adm group and will have read access to these files.
Additionally, an initscript bug
present from 2017-2019 caused the /var/log/dmesg log file to be generated
with world-readable permissions (644) and may still be world-readable on
some systems.
debugfs
Various areas of debugfs
(/sys/kernel/debug/*) may disclose kernel pointers.
debugfs is no longer readable by unprivileged users by default
since kernel version v3.7-rc1~$174^{2}$~57 on 2012-08-27.
This change pre-dates Linux KASLR by 2 years. However, debugfs may still be readable in some non-default configurations.
The following KASLD components read from debugfs:
- kmemleak.c — a direct-map pointer witness from the kmemleak report at
/sys/kernel/debug/kmemleak - ptdump_kernel_page_tables.c — the kernel virtual text base (
_text) from the page-table dump at/sys/kernel/debug/page_tables/kernel
The ftrace tracing interface (tracefs, /sys/kernel/tracing, historically mounted under debugfs) also exposes kernel text addresses:
- tracefs_available_filter_addrs.c — kernel text (and module) virtual addresses from
/sys/kernel/tracing/available_filter_functions_addrs(independent ofkptr_restrict) - tracefs_printk_formats.c — kernel text/rodata virtual addresses from the format strings at
/sys/kernel/tracing/printk_formats
Procfs and sysfs
The /proc and /sys pseudo-filesystems expose kernel addresses, memory
layout details, symbol information, and hardware configuration. Many of
these files are readable by unprivileged users by default.
The following KASLD components read from /proc:
- proc_kallsyms.c — kernel symbol addresses from
/proc/kallsyms - proc_modules.c — loaded module addresses from
/proc/modules - proc_zoneinfo.c — memory zone boundaries from
/proc/zoneinfo - proc_cpuinfo.c — CPU information from
/proc/cpuinfo - proc_pid_syscall.c — kernel stack pointer from
/proc/<pid>/syscall - proc_stat_wchan.c — wait channel address from
/proc/<pid>/stat - proc_timer_list.c — per-CPU timer base addresses from
/proc/timer_list - proc_net_sock_ptr.c — a kernel socket-object direct-map pointer from the socket field in
/proc/net/unix(printed with%pK: unmasked whenkptr_restrict=0, or for aCAP_SYSLOGreader) - zfs_dbgmsg.c — kernel virtual addresses from the OpenZFS debug-message log at
/proc/spl/kstat/zfs/dbgmsg(out-of-tree OpenZFS module; the pointer is printed in full, so it surviveskptr_restrict=2) - proc_kcore.c — kernel
_stext(and, on x86_64, the exact direct-map basepage_offset_base) from the/proc/kcoreELF program headers. Unlike the entries above this is not an unprivileged leak: opening/proc/kcorerequiresCAP_SYS_RAWIO(in the init user namespace) and reads are blocked by kernel lockdown (confidentiality). It targets the container-with-capabilities case — a process grantedCAP_SYS_RAWIO(e.g.docker --cap-add=SYS_RAWIOwith system paths unconfined, or--privileged) is init-ns root for that check and can read it. The text base is sound on decoupled-text arches only (x86_64/arm64/riscv64/s390), where the kernel text has a dedicated high mapping. The direct-map base is recovered asp_vaddr - p_paddr + PHYS_OFFSETfrom the linear-map (RAM) headers and pinned exactly, but only wherePHYS_OFFSETis the true runtime physical base (x86_64); elsewhere it is left to the bounding leaks.
The following KASLD components read from /sys:
- acpi_mrrm.c — physical memory range base addresses from the Intel ACPI MRRM table via
/sys/firmware/acpi/memory_ranges/ - boot_params_e820.c — x86 E820 physical memory map and initrd physical address from
/sys/kernel/boot_params/data - sysfs_cbmem_address.c — coreboot CBMEM physical memory addresses from
/sys/bus/coreboot/devices/ - sysfs_cxl_region.c — CXL memory region host physical addresses from
/sys/bus/cxl/devices/ - sysfs_devicetree_elfcorehdr.c — kdump crash kernel ELF core header physical address from
/sys/firmware/devicetree/base/chosen/ - sysfs_devicetree_initrd.c — initrd address from
/sys/firmware/devicetree/ - sysfs_devicetree_memory.c — memory regions from
/sys/firmware/devicetree/ - sysfs_devicetree_reserved_memory.c — reserved DRAM region addresses from
/sys/firmware/devicetree/base/reserved-memory/ - sysfs_devicetree_uefi_mmap.c — EFI memory map buffer physical address from
/sys/firmware/devicetree/base/chosen/linux,uefi-mmap-*(UEFI-booted device tree platforms) - sysfs_devicetree_kernel_end.c — physical end of the kernel image from the device-tree chosen node under
/sys/firmware/devicetree/base/chosen/ - sysfs_devicetree_memory_limit.c — the physical-RAM ceiling the kernel was instructed to honour from
/sys/firmware/devicetree/base/chosen/ - sysfs_devicetree_mmio.c — physical MMIO register bases from every device node in
/sys/firmware/devicetree/base/(world-readable0444, not subject tokptr_restrict) - sysfs_efi_runtime_map.c — EFI runtime map virtual and physical addresses from
/sys/firmware/efi/runtime-map/ - sysfs_firmware_memmap.c — firmware memory map from
/sys/firmware/memmap/ - sysfs_iommu_reserved_regions.c — physical DRAM addresses of IOMMU reserved regions from
/sys/kernel/iommu_groups/*/reserved_regions - sysfs_iscsi_transport_handle.c — iSCSI transport handle from
/sys/class/iscsi_transport/ - sysfs_kernel_notes_xen.c — Xen notes from
/sys/kernel/notes - sysfs_memory_blocks.c — memory block addresses from
/sys/devices/system/memory/ - sysfs_module_sections.c — module section addresses from
/sys/module/*/sections/ - sysfs_nd_region.c — NVDIMM/PMem region physical start addresses from
/sys/bus/nd/devices/region*/ - sysfs_nf_conntrack.c — netfilter conntrack hash from
/sys/module/nf_conntrack/ - sysfs_pci_resource.c — PCI BAR addresses from
/sys/bus/pci/devices/ - sysfs_qcom_rmtfs_mem.c — Qualcomm RMTFS reserved physical memory addresses from
/sys/class/rmtfs/ - sysfs_uio_map.c — UIO device memory map physical addresses from
/sys/class/uio/ - sysfs_vmcoreinfo.c — vmcoreinfo note physical address from
/sys/kernel/vmcoreinfo - kernfs_ns_hash.c — a KASLR-linked address (
&init_net) recovered from the readdir seek cookies (d_off) of the namespace-tagged/sys/class/netdirectory: kernfs folds the namespace tag into each entry's name hash, so the leak is unprivileged and independent ofkptr_restrict
Most of these are mitigated by kernel.kptr_restrict (for /proc/kallsyms,
/proc/modules, etc.) and root-only permissions on sensitive sysfs entries.
Boot configuration
Boot configuration and kernel config files can reveal whether KASLR is
enabled, the PAGE_OFFSET (vmsplit), and other layout-relevant settings.
The following KASLD components read boot configuration:
- boot_config.c — reads
/boot/config-*forCONFIG_RELOCATABLE,CONFIG_RANDOMIZE_BASE, andCONFIG_PAGE_OFFSET - proc_config.c — reads
/proc/config.gzfor the same configuration options - proc_cmdline.c — reads
/proc/cmdlineto check fornokaslr - hibernation_nokaslr.c — checks whether hibernation resume has disabled KASLR
Side-channels
There are a plethora of viable side-channel attacks which can be used to break KASLR, including microarchitectural timing attacks, transient execution attacks, and software side-channels that exploit timing variations in kernel algorithms and data structures.
The following table catalogues known side-channel KASLR attacks.
| Attack | Year | Status | References |
|---|---|---|---|
| KernelSnitch | 2025 | Implemented (experimental): kernelsnitch.c Futex hash-table timing leaks mm_struct directmap address (not _stext). x86_64, unprivileged. Requires --experimental (~1–30 min runtime). Nominally targeted by CONFIG_FUTEX_PRIVATE_HASH (v6.14+), but the unprivileged opt-out prctl PR_FUTEX_HASH_SET_SLOTS=0 pins the process back onto the global mm_struct-keyed hash and defeats it, so the leak remains live; upstream status unfixed. | KernelSnitch: Side-Channel Attacks on Kernel Data Structures (Maar et al., 2025) — NDSS 2025 lukasmaar/kernelsnitch |
| GhostWrite (CVE-2024-44067) | 2024 | T-Head XuanTie C910/C920 RISC-V only (2 CPU models); kernel ≥6.14 disables vector extension as mitigation. | GhostWrite RISCover: Differential CPU Fuzz Testing (Thomas et al., 2025) cispa/GhostWrite, cispa/RISCover |
| SLAM | 2024 | Requires Intel LAM / AMD UAI (no mainstream kernel support yet); Spectre-based, needs specific gadgets. | Leaky Address Masking: Exploiting Unmasked Spectre Gadgets with Noncanonical Address Translation (Hertogh et al., 2024) vusec.net/projects/slam, vusec/slam |
| SLUBStick (CVE-2024-26808) | 2024 | Achieves arbitrary kernel read/write (enabling KASLR bypass) via allocator timing side-channel, but requires a pre-existing heap vulnerability (UAF, heap overflow). Not a standalone KASLR bypass. | SLUBStick: Arbitrary Memory Writes through Practical Software Cross-Cache Attacks within the Linux Kernel (Maar et al., 2024) — USENIX Security 2024 |
| GhostRace (CVE-2024-2193) | 2024 | Intel and AMD x86_64. Speculative Race Conditions — serialization primitives (mutexes, spinlocks, RCU read locks) can be bypassed under speculative execution. The CPU speculatively traverses kernel data structures while the protecting lock is speculatively considered unheld, enabling speculative reads from kernel memory. Not a standalone bypass; requires a suitable speculative window in the kernel. Mitigated by inserting lfence after every potentially-speculatively-bypassed conditional branch in affected synchronization primitives. | GhostRace: Exploiting and Mitigating Speculative Race Conditions (Ragab, Barberis, Bos & Giuffrida, 2024) — USENIX Security 2024 vusec/ghostrace |
| Downfall (CVE-2022-40982) | 2023 | Mitigated by microcode on affected Intel CPUs (6th-11th gen); Gather Data Sampling, complex setup. | Downfall: Exploiting Speculative Data Gathering (Moghimi, 2023) |
| Timing Transient Execution | 2023 | Depends on Meltdown-type transient execution; mitigated by KPTI on all affected Intel CPUs. | Timing the Transient Execution: A New Side-Channel Attack on Intel CPUs (Jin et al., 2023) |
| Inception / SRSO (CVE-2023-20569) | 2023 | AMD x86_64 only; Zen 3 and Zen 4. Speculative Return Stack Overflow — phantom calls inserted by the branch predictor poison the return address predictor, causing return instructions to speculate to attacker-controlled targets in kernel context. Demonstrated end-to-end KASLR bypass via speculative reads of kernel memory. Mitigated by IBPB-on-entry or safe-ret (a retpoline variant that breaks speculative return chaining) on affected CPUs. | Inception: Exposing New Attack Surfaces with Training in Transient Execution (Trujillo, Wikner & Razavi, 2023) — USENIX Security 2023 comsec-group/inception |
| AMD Prefetch Attacks (CVE-2021-26318) | 2022 | Mitigated on Zen 3+ via microcode (AMD-SB-1017); redundant on older AMD / VMs where prefetch.c also works. | AMD Prefetch Attacks through Power and Time (Lipp et al., 2022) — USENIX Security 2022 AMD-SB-1017 amdprefetch/amd-prefetch-attacks |
| AMD RAPL power side-channel (CVE-2021-26318) | 2022 | Unprivileged RAPL access blocked since Linux 5.10; requires amd_energy module (not loaded by default); mitigated by same microcode as timing variant. | AMD Prefetch Attacks through Power and Time (Lipp et al., 2022) |
| EntryBleed (CVE-2022-4543) | 2022 | Implemented: entrybleed.c Intel x86_64 with KPTI enabled or disabled; AMD x86_64 with KPTI disabled. Requires kernel-version-specific offsets. Patched in kernel ~v6.2 (randomized per-CPU entry areas). | EntryBleed: Breaking KASLR under KPTI with Prefetch (CVE-2022-4543) (willsroot, 2022) EntryBleed: A Universal KASLR Bypass against KPTI on Linux (William Liu, Joseph Ravichandran, Mengjia Yan, 2023) |
| RETBLEED | 2022 | Kernel mitigated (IBRS/eIBRS, retpoline); requires specific Intel (6th-8th gen) or AMD (Zen 1/1+/2) CPUs. | RETBLEED: Arbitrary Speculative Code Execution with Return Instructions (Wikner & Razavi, 2022) comsec-group/retbleed |
| SLS (CVE-2021-26341) | 2022 | AMD Zen 1/2 only; requires eBPF JIT (restricted since Linux 5.8); mitigated by INT3/LFENCE after every unconditional branch. | The AMD Branch (Mis)predictor Part 2: Where No CPU has Gone Before (Wieczorkiewicz, 2022) Straight-line Speculation Whitepaper (ARM, 2020) |
| ThermalBleed | 2022 | Thermal side-channel operates at ms-second timescale; far too slow/noisy for KASLR (needs sub-µs resolution). | ThermalBleed: A Practical Thermal Side-Channel Attack (Kim & Shin, 2022) |
| Hertzbleed (CVE-2022-23823, CVE-2022-24436) | 2022 | Dynamic-frequency (DVFS) side-channel: under a power/thermal cap, core frequency depends on the data being processed, turning nominally constant-time code into data-dependent wall-clock time (observable via cpufreq or a reference-workload timer). Demonstrated against cryptographic keys (SIKE), not KASLR — no known unprivileged kernel operation has a frequency reaction that depends on a KASLR-placed address, so a KASLR application is unproven. Requires DVFS-observable bare metal (a VM guest cannot see real frequency reactions) and is slow (≈bits/hour). Intel 8th-gen+; AMD Zen 2/3. Mitigated by disabling Turbo / Precision Boost or capping frequency. | Hertzbleed: Turning Power Side-Channel Attacks Into Remote Timing Attacks on x86 (Wang, Paccagnella, He, Shacham, Fletcher, Kohlbrenner, 2022) — USENIX Security 2022 hertzbleed.com |
| MMIO Stale Data (CVE-2022-21123, CVE-2022-21125, CVE-2022-21127, CVE-2022-21166) | 2022 | Intel x86_64; Intel CPUs from Skylake through Alder Lake. MMIO read completions propagate stale data through shared microarchitectural buffers (fill buffers, load ports, store buffers) where it can be sampled cross-privilege. Four variants: SBDR (Shared Buffer Data Read), SBDS (Shared Buffer Data Sampling), SRBDS update (Special Register Buffer), and DRPW (Device Register Partial Write). Mitigated by VERW in kernel entry/exit paths (same mechanism as MDS) plus microcode update. | Processor MMIO Stale Data Vulnerabilities (Intel, 2022) kernel.org: Processor MMIO Stale Data Vulnerabilities |
| Spectre-BHB / Native BHI (CVE-2022-0001, CVE-2022-0002) | 2022 | Intel x86_64; bypasses eIBRS and Retpoline by poisoning the Branch History Buffer (BHB) from userspace before a syscall, causing indirect branches in kernel context to speculate to attacker-chosen targets. "InSpectre Gadget" (Hermans et al., 2024) provides a systematic framework for finding Native BHI gadgets in the Linux kernel and demonstrated end-to-end KASLR bypass via speculative kernel memory reads. Mitigated by BHI_DIS_S microcode feature and CLEAR_BHB instruction sequences in kernel entry/exit paths (≥v6.8). | Branch History Injection (Intel, 2022) InSpectre Gadget: Inspecting the Residual Attack Surface of Cross-privilege Spectre v2 (Hermans et al., 2024) — IEEE S&P 2024 vusec/inspectre-gadget |
| Spectre-BHB on ARM (CVE-2022-23960) | 2022 | ARM aarch64; affects Cortex-A57, A72, A73, A75, A76, A77, A78, Cortex-X1, Cortex-X2, Neoverse-N1, Neoverse-N2. Same primitive as Intel Native BHI — userspace poisons the Branch History Buffer before a syscall so indirect branches in EL1 speculate to attacker-controlled targets, enabling speculative reads of kernel memory. Naturally-occurring gadgets in upstream Linux are sufficient (no kernel patch needed); the InSpectre-Gadget framework finds them. Mitigated by CLEAR_BHB-equivalent loop sequences in kernel entry/exit paths (≥v6.8) and the CSV2/CSV3 ID feature reporting. Requires a userspace cycle counter; on hardened ARM64 kernels PMUSERENR_EL0.EN is clear by default and pmccntr_el0 traps to SIGILL — cntvct_el0 is too coarse (~50 ns) for the timing channel. Decode CPU part from /proc/cpuinfo: 0xd07 A57, 0xd08 A72, 0xd09 A73, 0xd0a A75, 0xd0b A76, 0xd0d A77, 0xd0e A78, 0xd44 X1, 0xd0c N1, 0xd49 N2. | Spectre-BHB / Branch History Injection on Arm CPUs (Arm, 2022) kernel.org: Spectre Side Channels (Arm-specific section) InSpectre Gadget: Inspecting the Residual Attack Surface of Cross-privilege Spectre v2 (Hermans et al., 2024) — applicable to Arm targets via the same gadget-finder framework |
| Memory deduplication timing | 2021 | Requires KSM enabled (disabled by default on most distros); primarily a VM-to-VM attack. | Memory deduplication as a threat to the guest OS (Suzaki et al., 2011) Breaking KASLR Using Memory Deduplication in Virtualized Environments (Kim et al., 2021) Remote Memory-Deduplication Attacks (Schwarzl et al., 2022) |
| VDSO sidechannel | 2021 | ARM64 only; requires custom kernel gadget in VDSO; mitigated by Spectre barriers in VDSO code. | VDSO As A Potential KASLR Oracle (Pettersson & Radocea, 2021) |
| EchoLoad | 2020 | Implemented (experimental): echoload.c Intel x86_64 only; relies on Meltdown zero-return behavior. Supports TSX, speculation, and signal-handler transient modes. No signal on non-vulnerable hardware (AMD, modern Intel with in-silicon Meltdown fix). Mitigated by KPTI on patched kernels. Requires --experimental. | KASLR: Break It, Fix It, Repeat (Claudio Canella, Michael Schwarz, Martin Haubenwallner, 2020) Store-to-Leak Forwarding: There and Back Again (Canella et al., 2020) — Slides, Blackhat Asia 2020 cc0x1f/store-to-leak-forwarding/echoload |
| PLATYPUS | 2020 | Unprivileged RAPL access restricted since Linux 5.10 (powercap driver); requires Intel CPU with specific RAPL interface. | PLATYPUS: Software-based Power Side-Channel Attacks on x86 (Lipp et al., 2020) |
| TagBleed | 2020 | Requires Intel CPU with tagged TLBs and a VMM environment; narrow applicability. | TagBleed: Breaking KASLR on the Isolated Kernel Address Space using Tagged TLBs (Koschel et al., 2020) renorobert/tagbleedvmm |
| SRBDS / CrossTalk (CVE-2020-0543) | 2020 | Intel x86_64; Intel CPUs from Core 6th gen through some 10th gen. The Special Register Buffer used by RDRAND, RDSEED, and SGX EGETKEY is shared across all logical cores on the same physical core. Data from one logical core's RDRAND result can be sampled by another via a Flush+Reload side-channel on the shared buffer. On kernels that use RDRAND for KASLR seeding, leaked values can constrain or reveal the KASLR seed. Demonstrated cross-VM leakage. Mitigated by serializing the Special Register Buffer with a microcode-injected fence around affected instructions. | CrossTalk: Speculative Data Leaks Across Cores Are Real (Ragab, Milburn, Razavi, Bos & Giuffrida, 2021) — IEEE S&P 2021 vusec/crosstalk kernel.org: SRBDS |
| MDS / ZombieLoad / RIDL / Fallout (CVE-2018-12130) | 2019 | Implemented (experimental): zombieload.c Intel x86_64 only; requires TSX (RTM) and an MDS-vulnerable CPU (pre-Ice Lake). Leaks kernel text base from stale line fill buffer (LFB) data after a syscall. Samples all 64 cache-line byte offsets and reconstructs kernel pointers from Flush+Reload histograms. Mitigated by MDS buffer clearing (VERW) on supported microcode; hardware fix in Ice Lake+. TSX disabled via microcode on most consumer CPUs since 2019. AMD CPUs are not affected. Requires --experimental. | ZombieLoad: Cross-Privilege-Boundary Data Sampling (Schwarz, Lipp, Moghimi, Van Bulck, Stecklina, Prescher, Gruss, 2019) — CCS 2019 RIDL: Rogue In-Flight Data Load (van Schaik, Milburn, Österlund, Frigo, Maisuradze, Razavi, Bos, Giuffrida, 2019) — S&P 2019, vusec/ridl Fallout: Leaking Data on Meltdown-resistant CPUs (Canella et al., 2019) — fallout_kaslr.c IAIK/ZombieLoad, zombieload_kaslr.c |
| Data Bounce | 2019 | Implemented: databounce.c Intel x86_64 only; requires TSX (RTM). Exploits store-to-load forwarding within a TSX transaction. Works with KPTI enabled or disabled, bare metal and VMs. TSX deprecated by Intel, disabled via microcode on most consumer CPUs since 2019 (TAA mitigation). | Store-to-Leak Forwarding: Leaking Data on Meltdown-resistant CPUs (Michael Schwarz, Claudio Canella, Lukas Giner, Daniel Gruss, 2019) cc0x1f/store-to-leak-forwarding/data_bounce |
| TAA / TSX Asynchronous Abort (CVE-2019-11135) | 2019 | Intel x86_64 only; requires an MDS-vulnerable CPU (pre-Ice Lake) with TSX enabled. A TSX transaction abort triggered asynchronously by the microcode fills the Line Fill Buffer with stale data from other logical cores' recent operations, which can then be sampled via a Flush+Reload channel. Distinct from ZombieLoad (which uses synchronous fault-based LFB sampling) — TAA uses the TSX asynchronous abort mechanism to trigger LFB fill. Shares the same VERW mitigation as MDS/ZombieLoad, shipped together in the November 2019 microcode release. TSX disabled via microcode on most consumer CPUs since 2019. | TSX Asynchronous Abort (Intel, 2019) kernel.org: TSX Async Abort |
| Meltdown | 2018 | Fully mitigated by KPTI on all vulnerable CPUs; KPTI enabled by default since 2018. | Meltdown: Reading Kernel Memory from User Space (Lipp et al., 2018) — USENIX Security 2018 IAIK/meltdown, paboldin/meltdown-exploit |
| Spectre v1 / v2 | 2018 | Heavily mitigated (retpoline, IBRS/eIBRS, eBPF verifier hardening). KASLR break requires eBPF JIT or specific kernel gadgets; eBPF restricted to CAP_BPF since Linux 5.8. | Spectre Attacks: Exploiting Speculative Execution (Kocher et al., 2018) Reading privileged memory with a side-channel (Jann Horn, 2018) speed47/spectre-meltdown-checker |
| SPECULOSE | 2018 | Equivalent to prefetch-style probing via speculative execution; fully mitigated by KPTI. | SPECULOSE: Analyzing the Security Implications of Speculative Execution in CPUs (Maisuradze & Rossow, 2018) |
| Prefetch side-channel | 2016 | Implemented: prefetch.c Intel and AMD x86_64. Requires KPTI to be disabled (kernel auto-disables KPTI on non-Meltdown-vulnerable CPUs: all AMD, Intel Ice Lake+). Does not require kernel-version-specific offsets. On some newer AMD microarchitectures (Zen 3+) the kernel-text prefetch timing differential is absent; the component reports no signal rather than emitting a false positive. | Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR (Daniel Gruss, Clémentine Maurice, Anders Fogh, 2016) Using Undocumented CPU Behaviour to See into Kernel Mode and Break KASLR in the Process (Anders Fogh, Daniel Gruss, 2016) — Blackhat USA xairy/kernel-exploits/prefetch-side-channel Fetching the KASLR slide with prefetch (Seth Jenkins, 2022) — prefetch_poc.zip |
Prefetch direct-map (page_offset_base) | 2016 | Implemented: prefetch_directmap.c The same prefetch primitive applied to the direct map (the linear mapping of all physical RAM), whose base page_offset_base is randomized independently of kernel text by CONFIG_RANDOMIZE_MEMORY on x86_64. Scans the 1 GiB (PUD)-aligned candidate bases and locates the mapped region's left edge, recovering page_offset_base — which resolves the virtual↔physical translation (physical leaks then map to virtual addresses and vice versa). Intel and AMD x86_64; 4-level paging only (the 5-level window spans tens of petabytes, too large for a flat scan, so it declines under la57). The 1 GiB-huge-page mapping produces a weaker differential than 2 MiB kernel text, so a run that cannot resolve the edge reports a weak/no signal rather than emitting a false base. | Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR (Daniel Gruss, Clémentine Maurice, Anders Fogh, 2016) |
| BTB side-channel | 2016 | Complex implementation; largely superseded by simpler prefetch / EntryBleed techniques. | Jump Over ASLR: Attacking Branch Predictors to Bypass ASLR (Evtyushkin et al., 2016) felixwilhelm/mario_baslr |
| DRAMA | 2016 | DRAM row-buffer conflict timing reverse-engineers the memory-controller addressing function, then recovers physical-address bits of a target page — read-only and non-destructive (distinct from RAMBleed/rowhammer below, which is a slow destructive write primitive). Combined with the kernel linear map, recovered physical bits of a pinned kernel object constrain the physical text base / PAGE_OFFSET. Not implemented. Requires bare metal (a VM guest's physical addresses are decoupled from host DRAM rows), a way to obtain buffers with known physical bits without pagemap (THP / contiguous allocation), and per-platform DRAM-geometry reverse-engineering. | DRAMA: Exploiting DRAM Addressing for Cross-CPU Attacks (Pessl, Gruss, Maurice, Schwarz, Mangard, 2016) — USENIX Security 2016 IAIK/drama |
| TSX/RTM abort timing (DrK) | 2016 | TSX deprecated by Intel, disabled via microcode on most consumer CPUs since 2019 (TAA mitigation). Redundant with Data Bounce on TSX-capable hardware. | TSX improves timing attacks against KASLR (Rafal Wojtczuk, 2014) DrK: Breaking KASLR with Intel TSX (Jang et al., 2016) — Blackhat USA vnik5287/kaslr_tsx_bypass |
| Double page fault timing | 2013 | Precursor to prefetch side-channel; fully mitigated by KPTI (Meltdown patches). Superseded by prefetch / EntryBleed. | Practical Timing Side Channel Attacks Against Kernel Space ASLR (Hund et al., 2013) |
| SIDT/SGDT IDT/GDT base leak | 2004 | Implemented: sidt.c x86/x86_64. Unprivileged SIDT instruction reads IDT register containing kernel pointer. Only works on pre-3.10 kernels where idt_table was in kernel BSS. Mitigated by IDT-to-fixmap remapping (v3.10, 2013; predates KASLR v3.14), KPTI (v4.15, 2018), and UMIP hardware (Intel Cannon Lake+ / AMD Zen 2+). Never viable against vanilla KASLR kernels. Originally used for VM detection (Red Pill, 2004); later demonstrated as a KASLR bypass against out-of-tree patches (Hund, 2013). | KASLR is Dead: Long Live KASLR (Gruss et al., 2017) — Section 2 lists SIDT as a known KASLR bypass Practical Timing Side Channel Attacks Against Kernel Space ASLR (Hund et al., 2013) Red Pill (Joanna Rutkowska, 2004) |
Note: Several related attacks (LVI, RAMBleed) are omitted from the table because they are not KASLR bypass techniques. LVI targets SGX enclaves; RAMBleed is a general memory read primitive (rowhammer-based, hours-slow).
The extra/check-hardware-vulnerabilities script performs rudimentary checks for several known hardware vulnerabilities, but does not implement these techniques.
See also:
- google/safeside — project to understand and mitigate software-observable side-channels (Google)
- Hardening the Kernel Against Unprivileged Attacks (Claudio Canella, 2022)
- Exploiting Microarchitectural Optimizations from Software (Moritz Lipp. 2021)
- transient.fail — overview of speculative / transient execution attacks (Graz University of Technology, 2020)
- LVI: Hijacking Transient Execution through Microarchitectural Load Value Injection (Jo Van Bulck, Daniel Moghimi, Michael Schwarz, Moritz Lipp, Marina Minkin, Daniel Genkin, Yuval Yarom, Berk Sunar, Daniel Gruss, and Frank Piessens, 2020)
- A Systematic Evaluation of Transient Execution Attacks and Defenses (Claudio Canella, Jo Van Bulck, Michael Schwarz, Moritz Lipp, Benjamin von Berg, Philipp Ortner, Frank Piessens, Dmitry Evtyushkin, Daniel Gruss, 2019)
- RAMBleed: Reading Bits in Memory Without Accessing Them (Andrew Kwong, Daniel Genkin, Daniel Gruss, Yuval Yarom, 2019) — google/rowhammer-test
- Micro architecture attacks on KASLR (Anders Fogh, 2016)
Syscall and interface leaks
The syscall boundary is the primary channel through which kernel data reaches userspace, making it a structurally significant source of KASLR bypass primitives. Several fundamental properties drive this attack surface:
Uninitialized bytes in copy-to-user paths. Every syscall that writes structured data to a user buffer — output parameters, queried state, socket message payloads, event records, notification packets — is a potential information channel. Bytes that are never explicitly written (alignment padding between struct members, trailing bytes in under-filled allocations, fields skipped on error paths) retain their stale kernel content and cross the trust boundary as part of the copy. The kernel's ABI stability requirement compounds this: struct layouts, including their padding holes, cannot be changed without breaking existing userspace, so a hole that exists in one release persists indefinitely. The ioctl interface is a concentrated instance of this pattern (see ioctl leaks), but it applies across all copy-to-user paths.
Kernel-pointer-derived values exposed by design. Many interfaces predate KASLR or were not designed with pointer exposure in mind and legitimately return values derived from kernel virtual addresses — event handles, timer IDs, object references, perf sample instruction pointers. The kernel address is never directly returned, but the value is a deterministic function of it. Whether this constitutes a leak depends entirely on the access controls applied — removing access control, or finding a bypass, converts a by-design interface into a KASLR oracle.
Access controls applied at the wrong abstraction level. A check that guards
a kernel address from unprivileged access is only as strong as the assumption
that the check and the data transfer happen in the same privilege context. When
kptr_restrict is enforced at read() rather than open(), a privileged
process can satisfy the open() and hand the descriptor to an unprivileged
reader. When a syscall applies access controls to the calling process's
credentials but not to an intermediate privileged agent acting on its behalf,
the check is bypassed without being subverted.
Privilege delegation via set-uid executables. The Unix set-uid mechanism
exists to let unprivileged processes perform specific privileged operations as
a side-effect of legitimate functionality. When that functionality involves
reading a restricted kernel interface, the unprivileged caller can observe the
elevated-privilege result. This is not a vulnerability in the set-uid binary
— it is working as designed — but the composition of set-uid execution with
a kptr_restrict-bypass-able interface produces an effective leak primitive.
Hypervisor and emulator transparency failures. A virtualization layer that emulates kernel instructions or system calls must faithfully replicate guest kernel behavior without exposing host kernel state to guest user processes. Bugs in the emulation of privilege-transitioning instructions — instructions that change the CPU privilege level or access a different address space — can cause the emulator to operate on host kernel memory while the guest believes it is in user space. The leak is not a kernel vulnerability; the kernel is never involved. The attack surface exists entirely within the emulation layer.
The following KASLD components exploit syscall and interface leaks:
- perf_event_open.c — samples kernel instruction pointer addresses via
perf_event_open()(requireskernel.perf_event_paranoid < 2) - perf_ksymbol_leak.c — BPF JIT / kprobe / ftrace trampoline addresses from
PERF_RECORD_KSYMBOLrecords viaperf_event_open()(requireskernel.perf_event_paranoid <= 0orCAP_PERFMON) - perf_lbr_sampling.c — kernel branch addresses via Last Branch Record sampling through
perf_event_open()(requireskernel.perf_event_paranoid <= 1orCAP_PERFMON) - perf_amd_branch_user.c — kernel
.textaddresses via an AMD branch-record filter bug: a user-only (PERF_SAMPLE_BRANCH_USER) request still captures kernel branches, so it leaks even at the defaultkernel.perf_event_paranoid=2when sampling one's own process - bpf_verifier_log.c — a kernel direct-map address from unmasked pointers in the BPF verifier log (requires
kernel.unprivileged_bpf_disabled=0, orCAP_BPF) - bpf_verifier_ksym.c — kernel
.textaddresses from the BPF verifier log, resolved against BTF from/sys/kernel/btf/vmlinux(requireskernel.unprivileged_bpf_disabled=0, orCAP_BPF) - alsa_seq_ext_ptr.c — a kernel direct-map address from an ALSA sequencer variable-length event echoed back through
/dev/snd/seq(unprivileged withaudio-group device access; independent ofkptr_restrict) - mincore.c —
mincore()heap page disclosure via uninitialized memory (CVE-2017-16994; patched in v4.15) - bcm_msg_head_struct.c — CAN BCM
bcm_msg_headstruct uninitialized 4-byte padding hole leaks kernel stack pointer viarecvmsg()(CVE-2021-34693; patched in v5.12) - pppd_kallsyms.c — set-uid-root
pppdopens and reads/proc/kallsymsas root: pre-v4.8 thekptr_restrict%pKcheck ran atread()time, whichpppdperforms with root credentials, so the symbols are unrestricted; v4.8 moved the check toopen() - qemu_tcg_iret.c — QEMU TCG
iretemulation performs the frame read as ring 0, so a ring-3 guest reads an exception handler's return address off the guest kernel's exception stack — a kernel.textpointer (patched in QEMU 9.1; not a kernel bug)
ioctl leaks
ioctl(2) is a catch-all syscall that dispatches through file_operations.unlocked_ioctl
into subsystem-specific handlers spread across drivers, filesystems, networking,
and IPC. The handler receives a request code (encoding direction, type, number,
and argument size via _IO/_IOR/_IOW/_IOWR) and a pointer to a userspace
buffer. The response path — copying data back to userspace — has historically
been a prolific source of kernel info leaks.
Four distinct mechanisms account for most ioctl info leaks:
Struct padding holes. C compiler-inserted alignment padding between struct
members is never initialized by assignment or by individual put_user() writes.
When the kernel copies a struct wholesale to userspace with copy_to_user(),
the padding bytes contain stale stack or heap data. This is the most common
class, covered by CERT C rule DCL39-C. Kernel-wide tools like KMSAN catch new
instances; many historical examples were fixed by inserting explicit memset()
before population, or by restructuring the struct to eliminate holes.
Uninitialized buffer copies. The handler allocates a buffer with kmalloc(),
__get_free_pages(), or a stack array, fills only part of it (e.g. because the
actual payload is smaller than the allocation, or because the write callback
leaves a trailing region untouched), then copies the full allocation to userspace.
The unfilled bytes contain stale slab or page allocator data, which frequently
holds kernel pointers from previously freed objects. The nilfs2
nilfs_ioctl_wrap_copy() path is a canonical example.
Stack variable leaks. The handler declares a struct or scalar on the stack
and passes it to a helper that may return early without initializing all fields
(e.g. on an unsupported index or error branch). The handler then copies the
partially-initialized stack variable back to userspace. KVM do_get_msr_feature()
is a canonical example: the msr.data field on the stack was never zeroed
before the early return on an unrecognized MSR index.
Unsanitized kernel pointer values. Some ioctl commands intentionally return
values derived from kernel virtual addresses — object handles, DMA buffer
identifiers, timer IDs — without applying kptr_restrict-equivalent masking.
These are not uninitialized-memory bugs but deliberate design choices later
recognized as leaks.
The ioctl attack surface is wide because:
- Handlers are scattered across hundreds of drivers and subsystems, each with its own review history and padding discipline.
- Many ioctls are only exercised on specific hardware or mounted filesystems, reducing the chance that automated testing catches the leak.
- The
copy_to_user()size argument is often computed from the ABI-fixed struct size, not from how much was actually written, making it structurally easy to under-fill.
The following KASLD components exploit ioctl info leaks:
- nilfs2_ioctl.c —
NILFS_IOCTL_GET_SUINFOcopies an uninitialized__get_free_pages()buffer; trailing page bytes contain stale kernel data (v2.6.30–v6.3) - ioctl_mmio_phys.c — physical MMIO base addresses from framebuffer (
FBIOGET_FSCREENINFO) and serial-deviceGETioctls, both ungated by capability orkptr_restrict - mali_timeline.c — kernel virtual addresses from the Arm Mali GPU driver timeline stream on
/dev/mali0(out-of-tree/third-party driver; CVE-2023-26083, fixed in r43p0+; unaffected bykptr_restrict)
See also:
- DCL39-C. Avoid information leakage when passing a structure across a trust boundary
- Exploiting Uses of Uninitialized Stack Variables in Linux Kernels to Leak Kernel Pointers (Haehyun Cho et al., 2020)
Brute force
Some memory layout properties can be determined by probing the address space directly, without reading any files or exploiting vulnerabilities.
The following KASLD components use brute-force probing:
- mmap_brute_vmsplit.c — locates the user/kernel split (
TASK_SIZE) on 32-bit systems by binary-searching the address space for the lowest pagemmaprefuses, which isPAGE_OFFSET(vmsplit) itself on x86_32 and a lower bound on it elsewhere
Weak entropy
The kernel is loaded at an aligned memory address, usually between PAGE_SIZE
(4 KiB) and 2 MiB on modern systems (see IMAGE_ALIGN definitions in
kasld/api.h).
This limits the number of possible kernel locations to the values in the KASLR slots table above.
The slot counts in that table are upper bounds. The kernel's KASLR placement code
enforces slot + kernel_size ≤ range_end, so positions near the top of the
randomization region where the image would overflow are never selected. Every
additional IMAGE_ALIGN bytes of kernel image size removes one trailing slot.
On architectures with tight entropy budgets — x86_64 and x86_32 (~500 slots,
~9 bits) and RISC-V64 (~512 slots) — a typical production kernel reduces the
effective slot count by 3–8%. On arm64 (~33M slots) and s390 (~131K slots) the
reduction is negligible.
Weaknesses in randomization can decrease entropy, further limiting the possible kernel locations in memory and making the kernel easier to locate.
Randomization failure at boot
Beyond the slot-count ceiling, KASLR can fail to apply any random
offset at boot. The kernel emits a KASLR disabled dmesg line but
continues to relocate the image to a firmware- or boot-stub-determined
position — not the link-time default. The result is 0 bits of KASLR
slot entropy, with the kernel landing at the same address on every
boot of the same (firmware, kernel build, hardware) tuple. Known
trigger conditions:
| Arch | Trigger | dmesg line |
|---|---|---|
| arm64 | EFI stub finds no EFI_RNG_PROTOCOL and no FDT /chosen/kaslr-seed (kaslr_get_seed() returns 0) | KASLR disabled due to lack of seed |
| arm64 | FDT remap failure during early KASLR init | KASLR disabled due to FDT remapping failure |
| s390 | CPU lacks the PRNG (prng_seed() failure) | KASLR disabled: CPU has no PRNG |
| s390 | Boot stub cannot allocate enough memory to apply the random offset | KASLR disabled: not enough memory |
| riscv64 EFI | No EFI_RNG_PROTOCOL (same shape as arm64) | — (not always emitted) |
This state is materially different from a deliberate opt-out
(nokaslr / CONFIG_RANDOMIZE_BASE=n / hibernation resume):
- Opt-out → kernel at
KERNEL_VIRT_TEXT_DEFAULT. Predictable from the compile-time linker layout alone. - Randomization failed → kernel at firmware-determined position. Predictable per-host (re-use a previously captured slide), but not from compile-time information.
KASLD emits a distinct scalar fact for each. The
dmesg_kaslr_disabled component classifies each KASLR disabled line
by its reason and emits SF_VIRT_KASLR_DISABLED +
SF_PHYS_KASLR_DISABLED (opt-out — both axes off) or
SF_VIRT_KASLR_RANDOMIZATION_FAILED + SF_PHYS_KASLR_RANDOMIZATION_FAILED (machinery failed). Only the former
pair drives the engine's virt_kaslr_disabled_pin and
phys_kaslr_disabled_pin rules. See
docs/kaslr.md — KASLR runtime states
for the full state taxonomy.
Slide baseline
The renderer reports KERNEL_VIRT_TEXT_DEFAULT (the per-arch compile-time
default kernel text base) as the slide baseline, sourced from
layout.kernel_text_default. When KASLR is disabled (opt-out), this
is the kernel's actual load address on arches that set
KASLR_DISABLED_PINS_VIRT_TEXT; on relocating arches the bootloader may
still place the image elsewhere, and the rule's window-containment
check catches that case. When KASLR randomization failed, the kernel
is NOT at KERNEL_VIRT_TEXT_DEFAULT — the engine resolves the actual
position from observable evidence rather than pinning to default.
See also:
- Linux KASLR Entropy (u1f383, 2025) — code-level walkthrough of x86_64 ktext slot calculation (
find_random_virt_addr) and kheap randomization (kernel_randomize_memory) - Another look at two Linux KASLR patches (Kryptos Logic, 2020)
- arm64: efi: kaslr: Fix occasional random alloc (and boot) failure
- Defeating KASLR by Doing Nothing at All (Seth Jenkins, 2025) - arm64 linear map is not randomized due to memory hotplug support; Pixel bootloader loads kernel at static physical address, making kernel virtual addresses fully predictable even with KASLR enabled.
Patched kernel bugs
There have been many kernel bugs which leaked kernel addresses to unprivileged users via uninitialized memory, missing pointer sanitization, using kernel pointers as a basis for "random" strings in userland, and many other weird and wonderful flaws. These bugs are regularly discovered and patched.
Patched kernel info leak bugs:
- https://github.com/torvalds/linux/search?p=1&type=Commits&q=kernel-infoleak
git clone https://github.com/torvalds/linux && cd linux && git log | grep 'kernel-infoleak'
Patched kernel info leak bugs caught by KernelMemorySanitizer (KMSAN):
- https://github.com/torvalds/linux/search?p=1&type=Commits&q=BUG: KMSAN: kernel-infoleak
git clone https://github.com/torvalds/linux && cd linux && git log | grep "BUG: KMSAN: kernel-infoleak"
Netfilter info leak (CVE-2022-1972):
Remote uninitialized stack variables leaked via Bluetooth:
- BadChoice: Stack-Based Information Leak (BleedingTooth) (CVE-2020-12352)
- Linux Kernel: Infoleak in Bluetooth L2CAP Handling (CVE-2022-42895)
- Info Leak in the Linux Kernel via Bluetooth (CVE-2017-1000410)
Remote kernel pointer leak via IP packet headers (CVE-2019-10639):
floppy block driver show_floppy kernel function pointer leak (CVE-2018-7273) (requires floppy driver and access to dmesg).
- Linux Kernel < 4.15.4 - 'show_floppy' KASLR Address Leak (Gregory Draperi. 2018)
- https://xorl.wordpress.com/2018/03/18/cve-2018-7273-linux-kernel-floppy-information-leak/
kernel_waitid leak (CVE-2017-14954) (affects kernels 4.13-rc1 to 4.13.4):
- wait_for_kaslr_to_be_effective.c (spender, 2017)
- https://github.com/salls/kernel-exploits/blob/master/CVE-2017-5123/exploit_no_smap.c (salls, 2017)
snd_timer_user_read uninitialized kernel heap memory disclosure (CVE-2017-1000380):
- Linux kernel 2.6.0 to 4.12-rc4 infoleak due to a data race in ALSA timer (Alexander Potapenko, 2017)
- snd_timer_c.bin (Alexander Potapenko, 2017)
Uninitialized kernel heap memory in ELF core dumps (CVE-2020-10732). fill_thread_core_info() in fs/binfmt_elf.c allocated regset data buffers with kmalloc(), which were not fully initialized by regset get() callbacks. Several kilobytes of stale kernel heap data (potentially containing kernel pointers) could be written to the core file and read by an unprivileged user. Trivially exploitable by crashing any program:
- google/kmsan#76: Uninitialized memory in ELF core dump
- Bug 1831399 - CVE-2020-10732 kernel: uninitialized kernel data leak in userspace coredumps
- fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() (Alexander Potapenko, 2020)
Uninitialized x86 FPU/xstate data in core dumps. copy_xstate_to_kernel() only copied enabled xstate features, leaving gaps between features uninitialized. Stale kernel memory was leaked through the NT_X86_XSTATE ELF core dump note:
RISC-V kernel gp register leaked to userland (CVE-2024-35871) (affects kernels 4.15 to 6.8.5). The kernel __global_pointer$ was exposed via childregs->gp in user_mode_helper threads (PID 1, core_pattern pipe handlers, etc), observable through kernel_execve register state, ptrace(PTRACE_GETREGSET), and PERF_SAMPLE_REGS_USER:
PPTP sockets pptp_bind() / pptp_connect() kernel stack leak (CVE-2015-8569):
Exploiting uninitialized stack variables:
- Structure holes and information leaks (Jonathan Corbet. 2010)
- C Structure Padding Initialization (Noah Pendleton. 2022)
- DCL39-C. Avoid information leakage when passing a structure across a trust boundary - SEI CERT C Coding Standard
- Exploiting Uses of Uninitialized Stack Variables in Linux Kernels to Leak Kernel Pointers (Haehyun Cho, Jinbum Park, Joonwon Kang, Tiffany Bao, Ruoyu Wang, Yan Shoshitaishvili, Adam Doupé, Gail-Joon Ahn. 2020)
- Leak kernel pointer by exploiting uninitialized uses in Linux kernel
- jinb-park/leak-kptr
- compat_get_timex kernel stack pointer leak (CVE-2018-11508).
- sctp_af_inet kernel pointer leak (CVE-2017-7558) (requires
libsctp-dev). - rtnl_fill_link_ifmap kernel stack pointer leak (CVE-2016-4486).
- snd_timer_user_params kernel stack pointer leak (CVE-2016-4569).
VT console font uninitialized heap leak. con_font_get() in drivers/tty/vt/vt.c allocated a font data buffer with kmalloc() and copied it to userspace without fully initializing it when the font width is not byte-aligned. Stale slab data could be read by any user with access to a virtual terminal (tty group). Affects v6.3 to v6.12:
AMD IBS (Instruction-Based Sampling) uninitialized perf stack leak. perf_ibs_handle_irq() in arch/x86/events/amd/ibs.c did not fully initialize the struct perf_ibs_data on-stack buffer before copying it to the perf ring buffer. On AMD CPUs with IBS support, stale kernel stack data (potentially containing kernel pointers) leaked to unprivileged perf readers. Affects v6.13 to v6.15 (AMD CPUs only):
memfd hugetlb non-zeroed folio leak. memfd_alloc_folio() in mm/memfd.c allocated hugetlb pool folios for memfds without zeroing, bypassing the page-fault path's normal folio_zero_user() call. Folios allocated via memfd_pin_folios() (currently only invoked by the udmabuf driver's UDMABUF_CREATE / UDMABUF_CREATE_LIST ioctls) retained whatever the prior hugetlb pool occupant left on them — up to 2 MiB of stale kernel or user data per folio, readable by any process holding the memfd via mmap() or read(). Requires vm.nr_hugepages > 0 (root sysctl, common on KVM hosts and DPDK / SPDK servers) and /dev/udmabuf RW access (default mode 0600; widened by some compositor / video udev rules). Affects v6.11 to v6.18:
Exploit primitives
Once a vulnerability yields an in-kernel primitive — most often an arbitrary read, but a constrained or relative read, an out-of-bounds read, a use-after-free read, or a write repurposed into a read all qualify — KASLR is bypassed as a step of the exploit rather than through an unprivileged interface leak. Which technique applies follows from the strength of the primitive, from a narrow over-read at one end to full arbitrary read/write or code execution at the other.
Exploitation makes two co-equal demands on KASLR, set by the strategy rather than by any single canonical slide:
- Control-flow hijack and fixed-symbol overwrite need the image slide
(
.text/.database) — gadget addresses, or the offset to a global such asmodprobe_pathorcore_pattern. - Data-only corruption — flipping
cred, page tables, or apipe_buffer, which sidesteps CFI/CET/SMEP — needs the direct-map (page_offset) base, the physical↔virtual pivot that makes an arbitrary heap object addressable.
On x86-64 the two bases are decoupled (RANDOMIZE_MEMORY), so which one an exploit
needs is set by its strategy. Recovering the image slide is a subtraction —
slide = leaked_pointer − link_time(symbol), checked against the image alignment
(CONFIG_PHYSICAL_ALIGN, 2 MiB on x86-64) — while recovering the direct-map base
is an alignment: a leaked heap pointer lies in the linear map, so page_offset
follows from rounding it down to the 1 GiB grid. A third strategy needs neither:
corruption that reaches its target relative to an object already held — up to
DirtyPipe-style page-cache overwrites — bypasses KASLR by not requiring any kernel
address.
Leaking a pointer from a reachable object
A relative, out-of-bounds, or use-after-free read that reaches an adjacent or reclaimed slab object leaks a pointer; which pointer it targets decides which base falls out.
To the image slide, many heap objects embed pointers with known link-time values:
- Operations tables —
file_operations,tty_operations,proto_ops,seq_operations,pipe_buffer->ops(anon_pipe_buf_ops),sk->sk_protand similar*_opsfields point into.rodata/.data/.text. Reclaiming a freed object with one that exposes such a field — the freedseq_operationsof anopen("/proc/…")file landing in a use-after-free slot is the archetype — yields a.text/.datapointer directly. - Deferred-work callbacks —
timer_list.function,work_struct.func. - Pointer-chasing — leak any object pointer (a
task_struct, a namespace), then traverse to one whose target is a fixed.data/.bsssymbol (init_task,init_cred,init_net,init_pid_ns,init_mm,init_ipc_ns); the traversal, not the first read, lands the known symbol.
To the direct-map base, the object's own storage is the target: any slab
object's address is a linear-map pointer, so leaking a heap pointer — a list
neighbour, a self-reference, a back-pointer — bounds page_offset regardless of
which object it belongs to. This is the data-only pivot: the recovered base makes a
sprayed or target object (cred, page-table pages, a pipe_buffer) addressable,
then feeds a data-only read/write primitive such as pipe_buffer.page AARW.
The msg_msg structure is the usual delivery vehicle for either: corrupting its
m_ts length or next pointer turns a one-shot overflow into a controlled
over-read into an adjacent object. A write primitive discloses nothing by itself,
but the same bug's write is frequently what builds the read.
Leaking a kernel pointer from a reachable object (msg_msg and related objects):
- Four Bytes of Power: Exploiting CVE-2021-26708 in the Linux kernel | Alexander Popov
- CVE-2021-22555: Turning \x00\x00 into 10000$ | security-research
- Exploiting CVE-2021-43267 - Haxxin
- Will's Root: pbctf 2021 Nightclub Writeup: More Fun with Linux Kernel Heap Notes!
- Will's Root: corCTF 2021 Fire of Salvation Writeup: Utilizing msg_msg Objects for Arbitrary Read and Arbitrary Write in the Linux Kernel
- [corCTF 2021] Wall Of Perdition: Utilizing msg_msg Objects For Arbitrary Read And Arbitrary Write In The Linux Kernel
- [CVE-2021-42008] Exploiting A 16-Year-Old Vulnerability In The Linux 6pack Driver
- CVE-2022-0185: Linux kernel slab out-of-bounds write: exploit and writeup — partial-overwrite of
msg_msg.m_tsextends the read to leakinit_ipc_nsvia a sprayedshm_file_data - [CVE-2022-1786] A Journey To The Dawn | kylebot's Blog —
timerfd_ctxlist pointers and armed-timer.textcallbacks - HTB UNI CTF 2021: Steam Driver Kernel Pwnable —
msg_msguser-copy KASLR rebase - Escaping the Google kCTF Container with a Data-Only Exploit (h0mbre) —
init_task/credtraversal, data-only - pipe_buffer exploitation experiments (Alexander Popov, 2026) — data-only
pipe_buffer.pageAARW; the direct-map pivot a recovered base feeds
Reading a fixed, KASLR-invariant structure
A true arbitrary read — one that dereferences an attacker-chosen absolute address
— can target a structure mapped at a fixed, KASLR-independent address whose
contents are slid kernel-text pointers, sidestepping the object grooming above.
The interrupt descriptor table is the canonical target: on x86-64 a read-only IDT
alias is mapped at the constant address 0xfffffe0000000000 (CPU_ENTRY_AREA_RO_IDT,
equal to CPU_ENTRY_AREA_BASE and unmoved by KASLR), while each gate still holds
the runtime address of its handler.
A 16-byte gate splits the 64-bit handler across offset_low (bits 0–15),
offset_middle (16–31) and offset_high (32–63). Because the image slide is
2 MiB-aligned, the low 21 bits of every handler are invariant and the top half is
the canonical 0xffffffff… window, so the only unknown bits — the slide entropy —
sit in offset_middle; a single 32-bit read across that field reconstructs the
handler, and subtracting the link-time symbol (gate 0 → asm_exc_divide_error)
yields the slide. This is the memory-disclosure successor to the unprivileged
SIDT/SGDT instruction leak (see Side-channels), which read
the IDT/GDT base: the fixed read-only alias and UMIP defeat the instruction, but
neither touches the gate contents, so an arbitrary read recovers the slide even
where SIDT is blocked.
- SIMPLE IS BETTER: Kernel Information Leak with Unprivileged Instructions (SIDT, SGDT) on x86
- make cpu-entry-area great again — kqx — fixed IDT mapping and
cea_offsetrandomization - SCTPhantom (CVE-2026-64564) — IDT gate 0 read from a repeatable 4-byte kernel read, bypassing UMIP
Resolving symbols from an in-kernel vantage
The strongest primitives — arbitrary read/write from kernel context, or kernel
code execution — make recovery direct rather than inferential: an attacker inside
the kernel can read the compiled kallsyms tables, read a .text pointer from a
CPU register (rdmsr MSR_LSTAR returns entry_SYSCALL_64), walk page tables from
CR3, or read descriptor-table and segment state from ring 0. The task shifts from
defeating KASLR to resolving symbol addresses under restrictions such as
kptr_restrict.
Leaking kernel addresses using privileged arbitrary read (or write) in kernel space:
- kptr_restrict – Finding kernel symbols for shell code (ryiron, 2013)
- CVE-2017-18344: Exploiting an arbitrary-read vulnerability in the Linux kernel timer subsystem (xairy, 2017):
Corruption without a leak
KASLR need not be recovered at all when the corruption reaches its target without a kernel address — the leak-free end of data-only exploitation:
- Partial pointer overwrite — because the slide is 2 MiB-aligned, the low bits of every already-slid kernel pointer are KASLR-invariant, so overwriting only the low byte(s) of an existing pointer retargets it within its aligned region (a nearby object or gadget) with no base knowledge.
- Relative writes — overwriting a field at a known offset inside an object
already held: a use-after-free-reclaimed
cred, a neighbouring slab object. - Content-only overwrites — DirtyPipe (CVE-2022-0847) rewrites read-only
page-cache contents through an uninitialized
pipe_buffer.flags, corrupting a file (a setuid binary,/etc/passwd) with no kernel pointer whatsoever; CVE-2026-31431 ("Copy Fail") reaches the page cache the same way throughalgif_aead/AF_ALGandsplice(). - Page-level use-after-free — reclaiming a freed physical page as a different object type (PageJack / Page-UAF) corrupts the overlapping structure data-only.
Writeups and targets:
- The Dirty Pipe Vulnerability (CVE-2022-0847) (Max Kellermann, 2022) — content-only page-cache overwrite, no KASLR required
- CVE-2026-31431 "Copy Fail" (2026) —
algif_aead/AF_ALG+splice()4-byte page-cache write corrupts a setuid binary for root, no KASLR required (fix reverts commit72548b093ee3) - Beyond Control: Exploring Novel File System Objects for Data-Only Attacks on Linux Systems (2024) — systematic study of data-only file-subsystem targets, many exploitable without a KASLR bypass
- Page-UAF / PageJack (Black Hat USA 2024) — page-level UAF PoCs (CVE-2021-22555, CVE-2022-0185, CVE-2022-0995, CVE-2023-5345); almost none require bypassing KASLR
- Exploit Methods/Function pointer overwrite - Linux Kernel Security Subsystem — where
.text/fops/descriptor-table pointers live
Probing candidate bases
With no leaked pointer to read directly, the base can still be found by probing the 2 MiB-aligned candidates: a survivable arbitrary read can scan them for the kernel's mapped contents, or — where nothing can be read back — an observable non-fatal side effect can distinguish a mapped from an unmapped address. A wrong guess that panics is single-shot, so a purely fatal primitive cannot be brute-forced this way, unlike the userland Brute force case.
- Overwriting the modprobe_path (ian.nl) — recovers the slide by scanning 2 MiB-aligned bases with an arbitrary read, then overwrites
modprobe_path
See also
- xairy/linux-kernel-exploitation — curated Linux kernel exploitation reference collection
- Kernel Address Space Layout Randomization (KASLR) — exploit-development walkthrough
- Exploiting a Linux Kernel Infoleak to bypass Linux kASLR (Marco Grassi, 2016)