Booting, Protection and Platform Security

These mitigations don't fix bugs; they make them much harder to exploit.

Concept

The Boot Process Firmware (UEFI, legacy BIOS, or a boot ROM on embedded SoCs) initializes the hardware and loads the boot loader.

Secure Boot verifies digital signatures of the boot loader and kernel so only trusted code runs; a TPM can record measurements of each stage (measured boot).

The kernel sets up page tables, interrupt tables, scheduling and drivers, mounts the root file system and starts PID 1.

On microcontrollers there is often no OS: the reset vector jumps to startup code that initializes the stack, copies .data, clears .bss and calls main.

Hardware Protection Mechanisms Privilege levels (rings, exception levels)

User code executing privileged instructions Virtual memory and page permissions

Processes accessing each other's memory or the kernel's NX / XD bit (W^X)

Memory being both writable and executable SMEP / SMAP (x86), PAN/PXN (ARM)

The kernel executing or accessing user memory unintentionally Devices doing DMA to arbitrary memory Timer interrupts One program monopolizing the CPU MPU (microcontrollers)

Tasks overwriting each other in RTOS systems without an MMU Software Hardening (defaults on modern Linux distributions)

Randomizes the addresses of stack, heap, libraries and PIE executables on every run

Makes the executable itself relocatable so ASLR applies to it Stack protector

The compiler inserts a check that detects corrupted stack frames and aborts RELRO + BIND_NOW

Makes relocation tables read-only after start-up Adds bounds checks to common library calls when sizes are known Non-executable stack GNU_STACK without E

These mitigations don't fix bugs; they make them much harder to exploit. The real defence is writing memory-safe code (bounds checks, safe string functions, sanitizers in testing, memory-safe languages where practical).

flowchart TB
    PWR["Power on / reset"] --> ROM["Firmware: UEFI or BIOS (or a microcontroller's boot ROM)"]
    ROM --> POST["Hardware initialization and self-test"]
    POST --> BL["Boot loader: GRUB, systemd-boot, U-Boot"]
    BL --> K["Kernel: decompress, set up memory, interrupts, drivers"]
    K --> INIT["First user process: init / systemd (PID 1)"]
    INIT --> SVC["Services and login"]

Why It Matters

Boot time and boot security matter for every product from servers to ECUs (automotive secure boot and ISO/SAE 21434 cybersecurity). Knowing which protections your platform provides — and verifying your binaries use them — is part of professional systems engineering.

Syntax

cat /proc/sys/kernel/randomize_va_space ASLR level (2 = full) readelf -h prog DYN type = PIE readelf -lW prog | grep GNU_STACK readelf -d prog BIND_NOW / RELRO flags cat /proc/cmdline Kernel boot parameters

Example

28.1 Boot parameters and firmware interfaces 28.2 Verifying that a binary uses the standard hardening features 28.3 ASLR in action

$ cat /proc/cmdline | tr ' ' '\n' | head -4
initrd=\initrd.img
WSL_ROOT_INIT=1
panic=-1
nr_cpus=8
$ ls /sys/firmware 2>/dev/null | head -5
acpi
memmap
$ cat /proc/sys/kernel/randomize_va_space
2
$ gcc -O2 hello.c -o hello
$ readelf -h hello | grep -E 'Type:'
  Type:                              DYN (Position-Independent Executable file)
$ readelf -lW hello | grep -E 'GNU_STACK|GNU_RELRO' | awk '{print $1, $(NF-1)}'
GNU_STACK RW
GNU_RELRO R
$ readelf -d hello | grep -E 'FLAGS|BIND_NOW' | awk '{print $2, $3, $4, $5}'
(FLAGS) BIND_NOW  
(FLAGS_1) Flags: NOW PIE
#include <stdio.h>
#include <stdlib.h>

int global;

int main(void)
{
    int local;
    void *heap = malloc(16);
    printf("code %p  global %p  heap %p  stack %p\n", (void *)main, (void *)&global, heap, (void *)&local);
    free(heap);
    return 0;
}
$ ./aslr
code 0x58c216c540c0  global 0x58c216c57014  heap 0x58c23e1472a0  stack 0x7ffe4c958d34
$ ./aslr
code 0x5f4939f980c0  global 0x5f4939f9b014  heap 0x5f493e51d2a0  stack 0x7ffefd63a5d4
$ ./aslr
code 0x57ba8ecf90c0  global 0x57ba8ecfc014  heap 0x57ba8f1bc2a0  stack 0x7fff247bf0a4

Expected Result

The kernel command line comes from the WSL boot configuration (initrd, number of CPUs); /sys/firmware/acpi shows the ACPI firmware interface; ASLR is at level 2 (full randomization).

The default GCC build on Ubuntu is a PIE (DYN), has a non-executable stack (GNU_STACK RW — no E), a read-only relocation region (GNU_RELRO) and immediate binding (BIND_NOW), i.e. full RELRO.

Three runs of the same program placed code, globals, heap and stack at different addresses each time.

Common Mistakes

Disabling mitigations "for performance" in production without measurement.

Believing mitigations make memory-unsafe code safe.

Shipping firmware without secure boot or with debug interfaces left open.

Best Practices

Keep compiler and distribution hardening defaults on; verify them in CI (readelf checks as above, or tools like checksec).

Test with AddressSanitizer and UndefinedBehaviorSanitizer; fuzz input parsers.

Use secure boot and signed updates on embedded products; lock debug ports in production.

Interview Relevance

Medium–high: "what happens when a computer boots?", "what is UEFI / Secure Boot?", "what is ASLR?", "what is the NX bit?", "what are protection rings?", "what does a stack protector do?".

Practice Questions

List the boot stages of an embedded Linux board with U-Boot.

Run readelf -d on three system binaries and check for BIND_NOW.

Explain why PIE is needed for ASLR to randomize the executable's own code.

Describe what a microcontroller's startup code must do before main.

Quick Quiz

Q1. (Multiple choice) Which process does the Linux kernel start first? A) The shell B) init/systemd (PID 1) C) The boot loader D) udev Answer: B.

Q2. (Predict the output) What value of randomize_va_space means full ASLR?

Answer: 2 (verified).

Q3. (True/False) A GNU_STACK segment with flags RW means the stack is executable.

Answer: False. RW without E means non-executable (verified for the default build).

Q4. (Find the bug) "We turned on ASLR and stack protectors, so buffer-overflow bugs in our parser no longer matter."

Answer: Mitigations only make exploitation harder; the bug must still be fixed (bounds checks, safe APIs, fuzzing).

Coding Challenge

Write a program that reads /proc/sys/kernel/randomize_va_space and prints a human-readable description of the ASLR level (0 = off, 1 = stack/libraries/vDSO, 2 = also heap).

#include <stdio.h>

int main(void)
{
    FILE *f = fopen("/proc/sys/kernel/randomize_va_space", "r");
    int level = -1;
    if (f) { if (fscanf(f, "%d", &level) != 1) level = -1; fclose(f); }
    const char *text[] = {"disabled", "stack, libraries and vDSO randomized", "full: also heap (brk) randomized"};
    printf("ASLR level %d: %s\n", level, level >= 0 && level <= 2 ? text[level] : "unknown");
    return 0;
}