Topic 04: Character Device Drivers & Direct Physical Memory Access

Target Duration: 2–4 minutes (~300–450 spoken words)
Focus: Pointwise verbal delivery covering dynamic character device registration, ioctl command dispatch, safe user/kernel boundary copying, and modifying physical RAM directly via the kernel's direct mapping.

🎯 Strategic Follow-Up Hook (From Elevator Pitch)

What You Mentioned: "Character drivers & physical memory writing"

Why It Was Done (The Motivation): Allow userspace to trigger privileged memory writes without bypassing MMU paging.

Problems Faced & How Solved (The Reality): Translated VA to PA, converted PA to virtual address via kernel direct mapping (phys_to_virt()), and wrote data directly.


🎙️ 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. Dynamic Chrdev Registered via alloc_chrdev_region Dynamically reserves major number and binds cdev to VFS. Eliminates major number collisions with existing drivers. 2.1/chardev.c:127-142
2. Auto Node Creation Called class_create & device_create Notifies sysfs/udev to create /dev/chardev. Eliminates manual root invocation of mknod in deployment. 2.1/chardev.c:139-142
3. Ioctl Dispatch Routed via .unlocked_ioctl Dispatches control commands via switch-case on ioctl numbers. Optimal design for structured commands and bidirectional parameter structs. 2.1/chardev.c:68-115
4. User Copy Boundary Used copy_from_user / copy_to_user Safely copies buffers while catching memory access faults. Prevents kernel crashes if user passes bad, unmapped, or null pointers. 2.1/chardev.c:73, 84
5. Direct Map Write Translated PA via phys_to_virt() Uses kernel direct mapping to access raw physical RAM. Allows modifying physical memory frames without altering MMU PTE permission bits. 2.1/chardev.c:91

❓ Anticipated Interview Questions & Crisp Answers

Q1: Why did you use an ioctl character device instead of standard VFS read/write or /dev/mem?

Answer: /dev/mem is heavily restricted or outright disabled in modern secure kernels (CONFIG_STRICT_DEVMEM), blocking user access to physical memory. Standard VFS read()/write() interfaces operate on unformatted byte streams, requiring ad-hoc packet parsing. An ioctl character driver provides strongly typed, bidirectional command dispatch with custom C structs (struct mem_query), passing virtual addresses, physical offsets, and byte buffers in a single atomic syscall with minimal overhead.

Q2: What security issues or crashes did you face when handling user pointers, and how does copy_from_user prevent them?

Answer: User space can supply invalid pointers, NULL pointers, or unmapped virtual addresses. Directly dereferencing a user pointer (*user_ptr) in Ring 0 triggers an unhandled page fault and an immediate kernel panic (Oops). Functions like copy_from_user() and copy_to_user() rely on kernel fixup exception tables: if the user pointer faults during copy, the MMU exception handler catches it, jumps to kernel fixup code, and safely returns the number of uncopied bytes (-EFAULT), protecting kernel stability.

Q3: How does writing to physical RAM via phys_to_virt() bypass user-space virtual memory protections?

Answer: In user space, pages can be mapped read-only via virtual page table permissions (e.g. PROT_READ on const strings or code segments). Attempting to modify them in user space triggers SIGSEGV. However, the 64-bit Linux kernel maps all physical RAM contiguously into the direct physical map (PAGE_OFFSET) with Ring 0 read-write permissions. By translating the virtual address to its physical page frame and calling phys_to_virt(pa), our driver writes directly through the kernel's alias mapping, successfully modifying the backing RAM without triggering a page fault.