1
votes

From what I've read in the book "Understanding the Linux kernel 3rd edition". That only the kernel can change the CPU execution mode from "user mode" to "kernel mode" and vice versa.

Each CPU model provides special instructions to switch from User Mode to Kernel Mode and vice versa. A program usually executes in User Mode and switches to Kernel Mode only when requesting a service provided by the kernel. When the kernel has satisfied the program's request, it puts the program back in User Mode.

How does the kernel do this? How is this operation possible only in that context? If I get the correct "recipe" (the special instructions each CPU model provides) can I do it in user space?

3

3 Answers

3
votes

I trust you already know why we have user and kernel mode - separation of trusted and untrusted software - so let's try to address the how. (I'm assuming a linux environment, as you're reading about the linux kernel.)

User programs can't really be trusted with low-level memory and hardware access; at best, the could overwrite one another's data, and at worst, they could damage the hardware. However, when a program just has to have access to low-level functions like memory allocation or hardware I/O, they can use a list of trusted system calls to perform their operations.

According to LINFO, the standard procedure for switching from user mode to kernel mode is to call software interrupt INT 0x80 - this assumes you're on an x86 processor. Specifically, the interrupt is thrown when a process in user mode attempts to access a privileged operation; this is illegal, and a trap (exception) is generated. Before the user process fires this interrupt, it stores in the process register (very small, very fast memory built into the processor) the system call number and any arguments to said call.

Once the user's program fires the interrupt, the kernel takes notice of it, checks the call and its argument, and then switches the mode bit (stored in the CS register) to kernel mode. The system call executes, the mode is switched back to user, and control returns to the user's program.


The operation is only possible in this context, in no small part because it's enforced by the hardware. I'm not sure if it's actually possible for a user to execute code in kernel space, but it's possible to trick the system into thinking you're root in order to access low-level hardware - that's called privilege escalation, and while such vulnerabilities and exploits are rare, they're a huge problem when they pop up.


tl;dr: User program tries to access a privileged instruction, gets blocked, and fires an interrupt requesting the kernel's help. The kernel catches it, switches the mode bit to go into kernel mode to perform the call, and then switches the bit back and returns to the user. Users shouldn't be able to execute in kernel mode, and if they can, you've got a serious problem on your hands.

1
votes

It is not totally true. The CPU will switch execution mode, and user space program can force such switch. Just that kernel should assure that all methods will get in kernel controlled memory.

System calls are one of the most common method to go in kernel mode. There are various methods do do a system call, e.g. with a software interrupt, or just a far call (far call: using a custom segment, specially marked on segment table).

But userspace programs could make CPU to switch into kernel, with exceptions (e.g. division by zero, so with explicit instructions), protection exceptions (accessing protected memory), debug registers, etc.

And hardware interrupts (timers, but also new inputs) could make the CPU to switch into kernel mode (in this case in a special interrupt mode, where the stack is small, but if there are many things to do, the interrupt code will cause to go into kernel mode after the interrupt it done).

Note: Any code in real mode could switch into protected mode, but this is relevant only for boot phase.

1
votes

A user process can instruct the processor to switch to kernel mode, but (in the absence of bugs) this is only possible in a way designed to give control to kernel software. The instruction to switch to kernel mode saves information about the user process and then changes program execution to kernel software. So when the switch to kernel mode is made, the software running is that of the kernel, not of your process. When the operating system first starts running on a processor, it configures the processor to support this operation.

This feature is used for user processes to request services from the kernel. If the user process wants to write data to disk or open a network connection or do anything else privileged, it formats a request (in some way that depends on the operating system and the hardware), and then executes an instruction to switch to kernel mode. This causes the kernel software to run, which examines the request and processes it.

When the kernel is done, it executes another special instruction that resumes running the process in user mode.

Normally, it is not possible for your process to request that it run in kernel mode, not through any sequence of instructions. If your process is privileged, it may be able to do various things with requests to the kernel that enable it to run software in kernel mode. (Most simply, on some systems, privileged processes can load kernel extensions and then use those for privileged operations.)