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:

KASLR bypass technique map: eight technique categories in three bands by requirement — read an interface (filesystem leaks, syscall and interface leaks, ioctl leaks), measure or infer (side-channels, brute force, weak entropy), and exploit a bug (patched kernel bugs, exploit primitives)

Table of Contents

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:

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 of kptr_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 when kptr_restrict=0, or for a CAP_SYSLOG reader)
  • 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 survives kptr_restrict=2)
  • proc_kcore.c — kernel _stext (and, on x86_64, the exact direct-map base page_offset_base) from the /proc/kcore ELF program headers. Unlike the entries above this is not an unprivileged leak: opening /proc/kcore requires CAP_SYS_RAWIO (in the init user namespace) and reads are blocked by kernel lockdown (confidentiality). It targets the container-with-capabilities case — a process granted CAP_SYS_RAWIO (e.g. docker --cap-add=SYS_RAWIO with 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 as p_vaddr - p_paddr + PHYS_OFFSET from the linear-map (RAM) headers and pinned exactly, but only where PHYS_OFFSET is the true runtime physical base (x86_64); elsewhere it is left to the bounding leaks.

The following KASLD components read from /sys:

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-* for CONFIG_RELOCATABLE, CONFIG_RANDOMIZE_BASE, and CONFIG_PAGE_OFFSET
  • proc_config.c — reads /proc/config.gz for the same configuration options
  • proc_cmdline.c — reads /proc/cmdline to check for nokaslr
  • 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.

AttackYearStatusReferences
KernelSnitch2025Implemented (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)2024T-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
SLAM2024Requires 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)2024Achieves 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)2024Intel 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)2023Mitigated by microcode on affected Intel CPUs (6th-11th gen); Gather Data Sampling, complex setup.Downfall: Exploiting Speculative Data Gathering (Moghimi, 2023)
Timing Transient Execution2023Depends 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)2023AMD 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)2022Mitigated 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)2022Unprivileged 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)2022Implemented: 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)
RETBLEED2022Kernel 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)2022AMD 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)
ThermalBleed2022Thermal 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)2022Dynamic-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)2022Intel 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)2022Intel 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)2022ARM 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 timing2021Requires 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 sidechannel2021ARM64 only; requires custom kernel gadget in VDSO; mitigated by Spectre barriers in VDSO code.VDSO As A Potential KASLR Oracle (Pettersson & Radocea, 2021)
EchoLoad2020Implemented (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
PLATYPUS2020Unprivileged 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)
TagBleed2020Requires 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)2020Intel 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)2019Implemented (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 Bounce2019Implemented: 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)2019Intel 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
Meltdown2018Fully 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 / v22018Heavily 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
SPECULOSE2018Equivalent 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-channel2016Implemented: 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)2016Implemented: 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-channel2016Complex implementation; largely superseded by simpler prefetch / EntryBleed techniques.Jump Over ASLR: Attacking Branch Predictors to Bypass ASLR (Evtyushkin et al., 2016)
felixwilhelm/mario_baslr
DRAMA2016DRAM 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)2016TSX 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 timing2013Precursor 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 leak2004Implemented: 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:

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() (requires kernel.perf_event_paranoid < 2)
  • perf_ksymbol_leak.c — BPF JIT / kprobe / ftrace trampoline addresses from PERF_RECORD_KSYMBOL records via perf_event_open() (requires kernel.perf_event_paranoid <= 0 or CAP_PERFMON)
  • perf_lbr_sampling.c — kernel branch addresses via Last Branch Record sampling through perf_event_open() (requires kernel.perf_event_paranoid <= 1 or CAP_PERFMON)
  • perf_amd_branch_user.c — kernel .text addresses 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 default kernel.perf_event_paranoid=2 when 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, or CAP_BPF)
  • bpf_verifier_ksym.c — kernel .text addresses from the BPF verifier log, resolved against BTF from /sys/kernel/btf/vmlinux (requires kernel.unprivileged_bpf_disabled=0, or CAP_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 with audio-group device access; independent of kptr_restrict)
  • mincore.cmincore() heap page disclosure via uninitialized memory (CVE-2017-16994; patched in v4.15)
  • bcm_msg_head_struct.c — CAN BCM bcm_msg_head struct uninitialized 4-byte padding hole leaks kernel stack pointer via recvmsg() (CVE-2021-34693; patched in v5.12)
  • pppd_kallsyms.c — set-uid-root pppd opens and reads /proc/kallsyms as root: pre-v4.8 the kptr_restrict %pK check ran at read() time, which pppd performs with root credentials, so the symbols are unrestricted; v4.8 moved the check to open()
  • qemu_tcg_iret.c — QEMU TCG iret emulation 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 .text pointer (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.cNILFS_IOCTL_GET_SUINFO copies 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-device GET ioctls, both ungated by capability or kptr_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 by kptr_restrict)

See also:

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 page mmap refuses, which is PAGE_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:

ArchTriggerdmesg line
arm64EFI stub finds no EFI_RNG_PROTOCOL and no FDT /chosen/kaslr-seed (kaslr_get_seed() returns 0)KASLR disabled due to lack of seed
arm64FDT remap failure during early KASLR initKASLR disabled due to FDT remapping failure
s390CPU lacks the PRNG (prng_seed() failure)KASLR disabled: CPU has no PRNG
s390Boot stub cannot allocate enough memory to apply the random offsetKASLR disabled: not enough memory
riscv64 EFINo 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:

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:

Patched kernel info leak bugs caught by KernelMemorySanitizer (KMSAN):

Netfilter info leak (CVE-2022-1972):

Remote uninitialized stack variables leaked via Bluetooth:

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).

kernel_waitid leak (CVE-2017-14954) (affects kernels 4.13-rc1 to 4.13.4):

snd_timer_user_read uninitialized kernel heap memory disclosure (CVE-2017-1000380):

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:

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:

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/.data base) — gadget addresses, or the offset to a global such as modprobe_path or core_pattern.
  • Data-only corruption — flipping cred, page tables, or a pipe_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 tablesfile_operations, tty_operations, proto_ops, seq_operations, pipe_buffer->ops (anon_pipe_buf_ops), sk->sk_prot and similar *_ops fields point into .rodata/.data/.text. Reclaiming a freed object with one that exposes such a field — the freed seq_operations of an open("/proc/…") file landing in a use-after-free slot is the archetype — yields a .text/.data pointer directly.
  • Deferred-work callbackstimer_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/.bss symbol (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):

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.

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:

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 through algif_aead / AF_ALG and splice().
  • 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:

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