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 0x7fff247bf0a4Expected 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;
}