User Mode vs Kernel Mode: How the OS Protects Itself - featured illustration
|

User Mode vs Kernel Mode: How the OS Protects Itself

Code on a modern computer executes in one of two privilege levels, user mode or kernel mode, and a thread moves between them as it works. The split is enforced by the CPU itself, and it is the reason a crashing web browser does not take Windows down with it, while a faulty graphics driver can. If you administer servers, understanding it explains three everyday things: why some crashes are harmless and others produce a blue screen or kernel panic, what the “system” versus “user” CPU numbers in monitoring tools mean, and why drivers and kernel modules deserve much more caution than ordinary software.

The two modes in one paragraph

Code in kernel mode can execute any CPU instruction and reach any memory address and hardware device that the hardware and hypervisor allow (features such as virtualization-based security can wall off some memory even from the normal kernel). Code in user mode cannot: it only sees its own virtual address space, and any attempt to run a privileged instruction or read kernel memory makes the CPU raise a fault, which the operating system turns into an error for that one process. On x86 processors this is implemented with “protection rings” numbered 0 to 3. Windows and Linux both use only two of them: ring 0 for the kernel and ring 3 for everything else. Other architectures such as ARM use different names (exception levels) for the same idea.

User mode Kernel mode
Runs Applications, services, shells, most subsystems The OS kernel, drivers, kernel modules
Memory Only its own private virtual address space All memory, including every process
Hardware No direct access; must ask the kernel Direct access to devices and privileged CPU instructions
If it crashes Usually only that process ends (killing a critical system process such as csrss.exe also stops Windows) The whole system stops (blue screen, kernel panic)
Examples Chrome, Word, sshd, nginx, explorer.exe ntoskrnl.exe, the Linux kernel, disk and network drivers

What actually lives where

On Windows, the kernel (ntoskrnl.exe), the Hardware Abstraction Layer and most device drivers run in kernel mode. Everything you normally launch, including Windows services such as the Print Spooler, runs in user mode. Microsoft’s own driver documentation describes the same split, and it is the reason driver quality matters so much: a bug in a kernel-mode driver can corrupt any memory, so Windows has no choice but to stop the machine.

On Linux, the kernel and loadable kernel modules (.ko files, shown by lsmod) run in kernel mode. All ordinary programs, from bash to postgres, run in user mode. Containers such as Docker do not change this: containerised processes are still ordinary user-mode processes that share the host’s kernel, which is why a kernel vulnerability affects every container on the host.

How a program crosses the boundary: system calls

A user-mode program cannot write to a disk or open a network socket itself. It asks the kernel to do it through a system call. The steps are the same everywhere:

  1. The program calls a library function such as fopen() in C, or CreateFile in the Windows API.
  2. The library places the request number and arguments in registers and executes a special CPU instruction (syscall on modern x86-64).
  3. The CPU switches to ring 0 and jumps to a fixed kernel entry point. The program cannot choose where it lands, which is what makes the transition safe.
  4. The kernel validates the arguments, performs the work, and returns to user mode with a result or an error code.

On Windows, the documented Win32 functions in kernel32.dll and friends eventually call the lower-level “native” functions in ntdll.dll, and those contain the actual transition into the kernel. Windows system call numbers change between releases, which is why applications are expected to use the Win32 API rather than calling the kernel directly. On Linux the numbers are a stable part of the kernel interface and are listed in the syscalls(2) manual page.

See it on a real system

You can watch system calls on Linux with strace. This command runs ls and prints a summary of which system calls it made and how often:

strace -c ls /etc > /dev/null

Typical output is a table of calls such as openat, read, write, getdents64 and close. Even a trivial program makes dozens of them. To see them in order for one file, use strace -e trace=openat cat /etc/hostname.

To see how much time a program spends in each mode, prefix it with time:

time tar -czf /tmp/test.tgz /var/log

The output reports real (wall-clock time), user (CPU time spent running the program’s own code in user mode) and sys (CPU time the kernel spent working on the program’s behalf, such as file and network I/O). In top, the same split appears as us and sy in the CPU line.

On Windows, open Task Manager, go to the Performance tab, right-click the CPU graph, choose Change graph to and enable Show kernel times. The graph then shows a darker area for time spent in kernel mode. Performance Monitor exposes the counters % User Time and % Privileged Time for the same purpose.

Reading the numbers as a sysadmin

  • High user time usually means the application itself is busy: computation, compression, a runaway loop. Profile or fix the application.
  • High system (kernel) time means the machine is spending its effort on I/O, networking, context switching or memory management. Look at disk and network throughput, the number of processes and threads, and swap activity. A sudden jump after installing a driver or security agent points at that component.
  • High interrupt or DPC time on Windows is a strong hint of a misbehaving driver, since these run in kernel context.

Why the design protects you

  • Stability: a bug in a user-mode program is contained. The kernel cleans up its memory and handles, and the rest of the system carries on.
  • Security: a normal program cannot read another program’s memory or reprogram hardware. Malware that only reaches user mode is limited by what the account and the OS permissions allow, while code that reaches kernel mode can hide itself from ordinary tools. That is why attackers value kernel-level access and why Windows requires signed drivers.
  • Fair sharing: because only the kernel touches hardware, it can schedule the CPU, memory and disks among all processes.

The boundary has a cost, and it has had real weaknesses. Every mode switch takes time, which is why high-performance software tries to reduce system calls. In 2018 the Meltdown vulnerability showed that some CPUs could leak kernel memory to user code through speculative execution, and operating systems responded with kernel page-table isolation, which made mode switches somewhat slower on affected hardware.

Common questions

Is “kernel mode” the same as being administrator or root?

No. Administrator and root are account privileges checked by the kernel, and the process still runs in user mode. Kernel mode is a CPU privilege level. An administrator can load a driver, which then runs in kernel mode, but that is a separate step.

Why does a driver crash cause a blue screen, but an application crash does not?

Because the driver shares the kernel’s address space and privilege level. When it corrupts memory or hits an unrecoverable error, the kernel cannot tell which data is still trustworthy, so Windows stops with a bug check (blue screen) and Linux with a kernel panic or oops.

Are there operating systems with less code in kernel mode?

Yes. Microkernel designs such as QNX and MINIX 3 keep drivers and services in user mode to reduce the impact of failures, at the cost of more messages between components. Windows and Linux are monolithic-style kernels with a lot of code in ring 0, though Windows has moved some drivers (for example many USB and printer drivers) to a user-mode framework.

Related reading on this site: how Windows boots, which shows when the kernel and its drivers are loaded, and the OSI and TCP/IP models.

Sources

Similar Posts

Leave a Reply

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