How Do ASLR and KASLR Work in Linux? – Free Linux Device Driver Course

Memory Layout Randomization – ASLR and KASLR

Free Linux Kernel Programming Course | EmbeddedPathashala

Part
1 of 2
Level
Intermediate
Topic
Linux Security / Memory

What is ASLR in Linux? Understanding Address Space Layout Randomization

When a program runs on Linux, it gets its own virtual address space — a private map of memory holding the code, stack, heap, and shared libraries. In older Linux systems, these memory regions always loaded at the same fixed addresses. That turned out to be a serious security problem. An attacker who knew the address of a function like system() in glibc could exploit a bug in your program and jump directly to that function to take control of the system.

To defeat this class of attack, Linux introduced ASLR (Address Space Layout Randomization) for user-space processes and KASLR (Kernel ASLR) for the kernel itself. These are fundamental memory protection features you must understand as part of any serious free Linux kernel programming course or free Linux device drivers course.

In this tutorial — part of the free embedded systems and Linux kernel development course at EmbeddedPathashala — you will learn exactly how ASLR and KASLR work, why they matter for security, and how to query and control them on your own Linux machine.

📋 What You Will Learn

  • Why fixed virtual addresses are a security weakness
  • How ASLR randomizes user-space process memory layouts
  • The three ASLR tunable values on Linux and what each one does
  • What KASLR is and how it extends randomization to kernel space
  • How to check ASLR and KASLR status on your system
  • How to enable or disable ASLR/KASLR using kernel parameters and procfs
  • Limitations of [K]ASLR as a security mechanism
  • Real-world examples demonstrating address randomization in action

🔧 Prerequisites

  • Basic understanding of the Linux process model and virtual memory
  • Familiarity with the Linux shell and procfs (/proc filesystem)
  • Completed earlier lectures in this free Linux kernel programming course (Virtual Address Space, VMAs, process memory maps)

Why Fixed Memory Addresses Are a Security Problem

Every running Linux process has a Virtual Address Space (VAS). This space contains:

  • The program’s own code (text segment)
  • Global and static variables (data/BSS segments)
  • The heap (for dynamic memory allocations)
  • Shared library mappings (like glibc)
  • The stack
  • The vDSO page (a kernel optimization for fast system calls)

Before ASLR existed, all of these regions loaded at predictable, fixed virtual addresses every single time a program ran. For a given architecture and software version, you could look up exactly where system() from glibc would be mapped in any process on that machine — tools like objdump, readelf, and nm made this trivial.

Process Virtual Address Space: Fixed Layout vs ASLR Layout

❌ Before ASLR (Fixed)
Stack — always at 0xBFFF0000
↓ grows down
vDSO — always at 0xBFFFE000
Shared libs — always at 0xB7500000
Heap — always at 0x08200000 ↑
Text/Code — always at 0x08048000
Attacker knows every address in advance

→

✅ After ASLR (Randomized)
Stack — random offset each run
↓ grows down
vDSO — random address each run
Shared libs — random base each run
Heap — random start each run ↑
Text/Code (PIE) — random each run
Attacker cannot predict any address

An attacker exploiting a buffer overflow vulnerability could use this knowledge to redirect program execution straight into a dangerous function. This attack style is called a return-to-libc attack. ASLR directly counters it by making memory layout unpredictable.

How ASLR Works – Randomization Under the Hood

ASLR works on a simple but powerful idea: instead of placing memory segments at their default base addresses, the Linux kernel applies a random page-aligned offset to each segment at process launch time. The word “page-aligned” means the offset is always a multiple of the system’s page size (typically 4096 bytes on x86), because memory can only be mapped in page-sized units.

The randomized regions in user space include:

  • Shared library load addresses — glibc, libpthread, and every other shared object
  • mmap-based allocations — any malloc() call requesting more than 128 KB goes through mmap(2) internally, and its result is randomized
  • Stack start address
  • Heap start address (with ASLR value = 2, see below)
  • vDSO page — the virtual Dynamic Shared Object that the kernel maps into every process for fast system call execution

Because all of these regions shift by a different random amount on each execution, an attacker who learns the address of one symbol in one run of a program cannot use that knowledge in a subsequent run — the address changes every time.

What ASLR Randomizes in the Process Virtual Address Space
Memory Region Randomized by ASLR? Notes
mmap(2) regions ✅ Value 1+ Includes large malloc calls >128 KB
Shared libraries ✅ Value 1+ Load address changes every run
Stack ✅ Value 1+ Start address shifted randomly
vDSO page ✅ Value 1+ Fast syscall helper page
Heap ✅ Value 2 only Default OS setting since kernel 2.6.25
Text/Code segment ⚠️ Only with PIE Requires Position Independent Executable build

Controlling User-Mode ASLR – The randomize_va_space Tunable

Linux exposes ASLR control through a procfs pseudo-file you can read and write as root:

/proc/sys/kernel/randomize_va_space

This tunable accepts three integer values. The table below explains each one:

ASLR Tunable Values – /proc/sys/kernel/randomize_va_space
Value What It Means What Gets Randomized
0 ASLR OFF — Can also be turned off at boot with the norandmaps kernel parameter Nothing. All regions use fixed addresses.
1 ASLR ON (partial) mmap-based allocations, stack, vDSO page, shared library load addresses, shared memory segments
2 ASLR ON (full) — OS default — Default since kernel 2.6.25 Everything from value 1, plus the heap start address is also randomized

On any standard Linux distribution today, this value will be 2 by default. You can verify it on your system with:

# Check current ASLR setting
cat /proc/sys/kernel/randomize_va_space

To temporarily change it (requires root, resets on reboot):

# Disable ASLR temporarily (testing/debugging only)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

# Enable partial ASLR
echo 1 | sudo tee /proc/sys/kernel/randomize_va_space

# Re-enable full ASLR (recommended)
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
⚠️ Important: Disabling ASLR using /proc/sys/kernel/randomize_va_space only affects user-space processes. It does not affect KASLR (kernel ASLR). To permanently change the setting across reboots, write to /etc/sysctl.conf instead.

Seeing ASLR in Action – A Practical Demonstration

The most direct way to observe ASLR working is to print the address of a function or a local variable from two separate runs of a program and compare the results.

/* File: check_aslr.c
 * Demonstrates ASLR by printing the address of a local variable
 * (on the stack) and the address of a glibc function across runs.
 * Compile: gcc -o check_aslr check_aslr.c
 */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int local_var = 42;

    /* Stack address changes each run when ASLR is active */
    printf("Stack variable address  : %p\n", (void *)&local_var);

    /* Heap address changes each run when ASLR value is 2 */
    void *heap_ptr = malloc(64);
    printf("Heap allocation address : %p\n", heap_ptr);

    /* glibc function address changes each run */
    printf("Address of printf()     : %p\n", (void *)printf);

    free(heap_ptr);
    return 0;
}

When ASLR is active (value 2), running this program twice gives completely different addresses each time. When ASLR is disabled (value 0), the addresses are identical across every run.

To demonstrate this from the shell:

# Run twice in a row with ASLR enabled and compare outputs
gcc -o check_aslr check_aslr.c
./check_aslr
./check_aslr

# Now disable ASLR and try again
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
./check_aslr
./check_aslr

# Re-enable ASLR when done
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

You will clearly see addresses differ between runs with ASLR on, and stay identical with ASLR off. This is the core behavior that defeats predictable-address attacks.

Limitations of ASLR – It Is Statistical, Not Absolute

ASLR is a strong defense but it is not a perfect one. The randomization depends on how many bits of entropy are available for the offset. On 32-bit systems, the virtual address space is only 4 GB, and the number of possible random positions is limited — an attacker with enough attempts (a brute-force approach) might guess a valid address.

On 64-bit systems the address space is vastly larger, which gives ASLR much stronger entropy, but even there:

  • Not all bits of the address are randomized — page alignment reduces the bit count available for randomization
  • An information leak vulnerability (such as a format string bug) can expose the actual runtime addresses to an attacker, completely defeating ASLR for that process
  • Brute-force attacks remain possible when a crashed process is quickly restarted without re-randomizing
💡 Key Insight: ASLR is best understood as a probabilistic mitigation — it raises the cost and difficulty of exploitation significantly, but does not guarantee safety on its own. It should always be combined with other protections like stack canaries, NX (No-Execute) bits, and secure coding practices.

Common Mistakes When Working with ASLR

  • Forgetting to re-enable ASLR after debugging — Developers disable ASLR to get reproducible addresses during debugging but forget to turn it back on. Always re-enable it after your debugging session.
  • Assuming ASLR protects statically-linked binaries fully — A binary compiled without Position Independent Executable (PIE) support has its text segment at a fixed address even with ASLR enabled. Use gcc -fPIE -pie to enable PIE.
  • Treating ASLR as the only security layer — ASLR alone is insufficient. Combine it with other kernel hardening features.
  • Confusing ASLR and KASLR — ASLR protects user-space processes. KASLR protects the kernel itself. They are independent — you need both enabled for complete protection.

📝 Part 1 Summary – Key Takeaways

  • Fixed virtual addresses allow attackers to plan exploits using known function locations
  • ASLR applies a random page-aligned offset to memory regions at process launch time
  • The /proc/sys/kernel/randomize_va_space tunable controls ASLR behavior with values 0, 1, and 2
  • Value 2 (the default) randomizes mmap regions, stack, vDSO, shared libraries, and the heap
  • ASLR is statistical protection — information leaks or brute force can still defeat it
  • ASLR and KASLR are independent — one protects user space, the other protects kernel space

Leave a Reply

Your email address will not be published. Required fields are marked *