Topic 01: LKM Fundamentals, Lifecycle Hooks & RCU Process Inspection

Target Duration: 2โ€“4 minutes (~300โ€“450 spoken words)
Focus: Pointwise verbal delivery covering Ring 0 out-of-tree execution, module_init/module_exit, module_param, circular task_struct traversal, and RCU locking semantics.

๐ŸŽฏ Strategic Follow-Up Hook (From Elevator Pitch)

What You Mentioned: "Kernel modules & lockless process inspection"

Why It Was Done (The Motivation): Safely inspect task_struct and children list in Ring 0 without stalling the kernel scheduler.

Problems Faced & How Solved (The Reality): Solved using rcu_read_lock() and list_for_each_entry_rcu(), preventing race conditions during process fork/exit.


๐ŸŽ™๏ธ Pointwise Spoken Speech (Word-for-Word Delivery)


๐Ÿ“‹ Step-by-Step Summary (What, How & Why)

Step What Was Done How It Works Why This Mechanism / Order Code Reference
1. Lifecycle Setup Implemented module_init & module_exit Compiles as .ko via Kbuild; hooks into insmod and rmmod. Ring 0 modules must cleanly release all allocated structures to prevent kernel panics. 1/lkm1.c:30-31
1/lkm2.c:59-60
2. Parameter Binding Configured module_param Defines static variables populated by insmod arguments. Allows dynamic target selection (e.g., target PID) without recompiling module source. 1/lkm2.c:11-12
3. Task Iteration Traversed all tasks via for_each_process Iterates circular doubly linked list of task_struct starting at init_task. Enables global process inspection directly from kernel memory. 1/lkm1.c:17-21
4. Hierarchy Walk Resolved PID & traversed children list Used find_vpid() $\rightarrow$ pid_task() and traversed task->children. Safely navigates the process tree to identify parent-child relationships. 1/lkm2.c:39-48
5. RCU Synchronization Guarded traversal with rcu_read_lock Enclosed reads in RCU read-side critical sections. Prevents use-after-free without acquiring expensive blocking locks during concurrent forks/exits. 1/lkm2.c:37, 50

โ“ Anticipated Interview Questions & Crisp Answers

Q1: Why inspect process structures directly in Ring 0 instead of reading /proc or running ps from user space?

Answer: User-space utilities like ps parse thousands of pseudo-files under /proc/[pid]/stat, which incurs significant VFS overhead, context switching, and string parsing. Furthermore, /proc snapshots are not atomic across processesโ€”by the time user space finishes reading, child processes may have exited or reparented. Inspecting processes directly in Ring 0 allows atomic, sub-microsecond traversal of kernel task structures (struct task_struct) directly from memory, resolving PID namespaces via find_vpid() and pid_task() without file system latency.

Q2: What race conditions can occur while iterating tasks concurrently, and how does RCU solve them?

Answer: The Linux task list is constantly modified as processes fork, terminate, and exit. If a module iterates the list using raw pointers, another CPU might free a terminating task's task_struct, leading to a fatal use-after-free kernel crash. Holding a heavy global write lock like tasklist_lock would halt scheduling across all CPUs. Instead, wrapping traversals in rcu_read_lock() / rcu_read_unlock() ensures lockless read access: even if a task is unlinked, its memory cannot be reclaimed until our CPU completes its critical section and passes a grace period.

Q3: What happens if an LKM fails to clean up a registered resource in module_exit()?

Answer: In Linux kernel space, there is no automatic garbage collection. If module_exit() fails to unregister a character device, procfs entry, or sysfs attribute, the kernel's core dispatch tables continue pointing to the memory where the module was mapped. When rmmod completes and unmaps the module's code pages, any subsequent read/write access to that dangling address triggers an immediate Ring 0 page fault and fatal kernel panic (Oops). All allocations and registrations must be strictly unwound in reverse order of initialization.