How does copy_from_user from the Linux kernel work internally? - linux

How exactly does the copy_from_user() function work internally? Does it use any buffers or is there any memory mapping done, considering the fact that kernel does have the privilege to access the user memory space?

The implementation of copy_from_user() is highly dependent on the architecture.
On x86 and x86-64, it simply does a direct read from the userspace address and write to the kernelspace address, while temporarily disabling SMAP (Supervisor Mode Access Prevention) if it is configured. The tricky part of it is that the copy_from_user() code is placed into a special region so that the page fault handler can recognise when a fault occurs within it. A memory protection fault that occurs in copy_from_user() doesn't kill the process like it would if it is triggered by any other process-context code, or panic the kernel like it would if it occured in interrupt context - it simply resumes execution in a code path which returns -EFAULT to the caller.

regarding "how bout copy_to_user since the kernel is passing on the kernel space address,how can a user space process access it"
A user space process can attempt to access any address. However, if the address is not mapped in that process user space (i.e. in the page tables of that process) or if there is a problem with the access like a write attempt to a read-only location, then a page fault is generated. Note that at least on the x86, every process has all the kernel space mapped in the lowest 1 gigabyte of that process's virtual address space, while the 3 upper gigabytes of the 4GB total address space (I'm using here the 32-bit classic case) are used for the process text (i.e. code) and data.
A copy to or from user space is executed by the kernel code that is executing on behalf of the process and actually it's the memory mapping (i.e. page tables) of that process that are in-use during the copy. This takes place while execution is in kernel mode - i.e. privileged/supervisor mode in x86 language.
Assuming the user-space code has passed a legitimate target location (i.e. an address properly mapped in that process address space) to have data copied to, copy_to_user, run from kernel context would be able to normally write to that address/region w/out problems and after the control returns to the user, user space also can read from this location setup by the process itself to start with.
More interesting details can be found in chapters 9 and 10 of Understanding the Linux Kernel, 3rd Edition, By Daniel P. Bovet, Marco Cesati. In particular, access_ok() is a necessary but not sufficient validity check. The user can still pass addresses not belong to the process address space. In this case, a Page Fault exception will occur while the kernel code is executing the copy. The most interesting part is how the kernel page fault handler determines that the page fault in such case is not due to a bug in the kernel code but rather a bad address from the user (especially if the kernel code in question is from a kernel module loaded).

The best answer has something wrong, copy_(from|to)_user can't be used in interrupt context, they may sleep, copy_(from|to)_user function can only be used in process context,
the process's page table include all the information that kernel need to access it, so kernel can direct access the user space address if we can make sure the page addressed is in memory, use copy_(from|to)_user function, because they can check it for us and if the user space addressed page is not resident, it will fix it for us directly.

The implementation of copy_from_user() system call is done using two buffers from different address spaces:
The user-space buffer in user virtual address space.
The kernel-space buffer in kernel virtual address space.
When the copy_from_user() system call is invoked, data is copied from user buffer to kernel buffer.
A part (write operation) of character device driver code where copy_from_user() is used is given below:
ssize_t cdev_fops_write(struct file *flip, const char __user *ubuf,
size_t count, loff_t *f_pos)
{
unsigned int *kbuf;
copy_from_user(kbuf, ubuf, count);
printk(KERN_INFO "Data: %d",*kbuf);
}

Related

Linux - Accessing mmap()ed memory from Thread from Userspace in Kernel Space

Mapped this memory in my Thread in Userspace:
b7fd0000-b7fd1000 rwxp 00000000 00:00 0
Thread is running (endless loop)
Made a breakpoint in the Kernel and trying to access it:
Thread 466 received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 3908]
0xc10d4060 in kgdb_breakpoint ()
(gdb) x/01i 0xb7fd0000
0xb7fd0000: Cannot access memory at address 0xb7fd0000
But it is not accessible.
How can I access 0xb7fd0000 from Kernel space? What address will be under?
Is it even possible?
Thanks,
The address the memory will appear under depends on which user space context is currently mapped.
The way this works is, some of the virtual addresses are reserved to the kernel, and these are the same in all contexts. This is why you can set a break point on a kernel address without worrying about which user space process is currently mapped.
For user space, this is not the case. Each time a new process is mapped, the virtual addresses for US change completely.
This is, likely, an X-Y problem. You're trying to do something, and you think that a kernel level break point is how you want to achieve it.
Taking a guess, you want your kernel driver to do something to communicate with your user space thread. If that's the case, your best bet is to export a character device, and have the userspace open it and mmap from there (rather than just an anonymous mmap). You can then control which memory it receives, and thus also map it to the kernel address space, where pointers are stable.
I'm not expert in kgdb but it will be worth checking current->pid at the time breakpoint is hit, contains pid of the process you're tracking. This is because although memory location inside kernel space has been hit, the user space process may not be the one you are interested in. Also to guard against possibility of pages being swapped out, it might be safer to lock mapped pages using mlock.
There are at least two things to pay attention to.
When to break. If you simply hit crtl-C in the kernel debugger, you don't know what the userspace context is going to be. It could be any userspace process. You want the kernel debugger to pause and give you control when the userspace context refers to the process you are interested in. One way to do this is as follows :- If you have the ability to recompile the kernel, add a new system call. Invoke this system call from the userspace process, after the region is mmap'd in. Start debugging the kernel after placing a breakpoint on the newly added system call. When the breakpoint is hit, you know for a fact that the userspace context is that of the process one you are interested in.
Virtual memory late binding. Even if you follow the steps in [1], you will still have trouble when accessing the contents of the buffer in userspace, if you have not read / written anything in that location. Make sure that after mmap'ing the region, you either read or write to the mmap'd location before invoking your newly added system call.

write access for kernel into a readonly segment

Until now I thought the kernel has the permissions to write in readonly segments. But this code has brought a lot of questions
int main() {
char *x = "Hello World";
int status = pipe((int*)x);
perror("Error");
}
The output of the code is
Error : Bad Address
What my argument is, "Since the pipe function executes in kernel mode the ro segment must be writable by kernel". Which doesn't seem to be the case here. Now my questions are
How kernel protects the memory segments which are readonly?
Or am I assuming wrong about the kernel's capabilities?
Much like the user space, the kernel's address space is subject to whether a particular virtual address (also called a logical address) is mapped as readable, writable and executable. Unlike the user space though, the kernel has the free rein to map a group of virtual addresses with a page and change the page permission attributes. However, just because the kernel has the ability to map a page as writeable, does not mean the address stored in char*x was paged in the kernel's address space as writable, or even paged at all, at the time of the pipe call.
The way the kernel protects regions of memory is with a piece of hardware called a memory management unit (MMU). The MMU is what performs the mapping of virtual to physical addresses and enforces permissions in those regions. The kernel is more or less given free rein to configure the MMU. Unlike kernel space, user space code should be unable to access the MMU. Since the user space can not access the MMU, it can not change the page table's mappings or the permission attributes of a page. This effectively means that user space has to use the address space mapping and the permissions set by the kernel.
I don't understand where the "kernel can write to ro pages" assertion comes from. If the kernel wants to it can remap memory however it sees fit of course, but why would it do that for this case?
I presume you are running on x86. On this arch the kernel splits the address space into 2 parts (user/kernel). When you switch to the kernel, userspace is still mapped So in particular when the kernel wants tries to write to the provided address, it hits the same mapping your userspace process would. Since the mapping does not allow write access, the operation fails.
For the sake of argument let's say this would not hold true. That is, whatever read-only mapping is in userspace, the kernel will write to it anyway and that will work. Well, that would be an instant security problem - consider a file you can only read/exec, like the glibc. it is mapped read-only/exec. And now you make the kernel write to area, effectively changing the file for everyone. So why not in particular do read(evilfd, address_of_libc, sizeo_of_libc); and bam, you just managed to overwrite the entire lib with data of your choice.

How kernel threaduse memory descriptor(mm_struct) of last ran process in Linux?

Some of the points mentioned in the Linux kernel Development (by Robert
Love) book about mm_struct and kernel thread are :
"Kernel threads do not have a process address space and therefore do not
have an associated memory descriptor. Thus, the mm field of a kernel
thread's process descriptor is NULL. "
"Because kernel threads do not have any pages in user-space, they do not
really deserve their own memory descriptor and page tables (page tables are
discussed later in the chapter). Despite this, kernel threads need some of
the data, such as the page tables, even to access kernel memory."
"Kernel threads do not have an address space and mm is NULL. Therefore, when
a kernel thread is scheduled, the kernel notices that mm is NULL and keeps
the previous process's address space loaded. The kernel then updates the
active_mm field of the kernel thread's process descriptor to refer to the
previous process's memory descriptor. The kernel thread can then use the
previous process's page tables as needed."
Now my queries are:
1. First it is mentioned that the kernel threads dont have any page in user
space and hence they dont deserve memory desriptor and page tables and in
the next line it says it needs some data such as page tables to access
kernel memory. What page table it is referring here?? Every process has its
own page table for mapping the virtual to physical address, why kernel
thread requires that?
How page table use by kernel thread?
Every thread whether its a user-space or kernel space process requires a page-table. The kernel address space (Virtual Memory address space) is directly mapped to the physical address space where as the user-space address space isn't directly mapped. Moreover the user-space application address space mappings keeps changing as the new processes are created, terminated, swapped whereas the kernel space mappings remain constant.
To learn more you can visit the following link :-
Process address Space
Or post the queries here.
There are some usespace applications and kernel threads in your system. Every virtual address space consists of kernel and user part. Kernel is the same for all processes, user part is different.
Every process has its own page table for mapping the virtual to
physical address, why kernel thread requires that?
Kernel threads need page tables to make translation from virtual address to physical while accessing memory.
How page table use by kernel thread?
Imagine a simple case, memory write such as a[i] = 5; in kernel space. This one typically goes through MMU, which use page tables to get physical address according to virtual address (in this case &a[i]). So there is no something special about kernel threads, the difference is that on context switch they don't change pgd (page global directory), they use pgd of last process, because all processes have the same kernel part and you can pick just last one (see actime_mm) and it will be ok.

How an actual system call is made?

I have a question about how an actual system call is made. I know that the magic of system call (like read etc.) is done in C library but don’t understand the exact mechanism. My main issues are
The c library routine is in user address space; then how can it get the address of the interrupt service routines. Are interrupt service routines predefined(on boot up) in physical memory?.
Even if somehow the ISR routine is called how does the address space change? I mean before we start the execution of ISR how will the 'page table base register' change to point to kernel's page table. If the 'C' routine does it then how does it know the address of Kernel's page table?
How are parameters copied from user space to kernel space?
Please excuse me if my questions are too basic but I am new to this. :)
Thanks
Rohit
On most systems, there's an instruction that can be executed by user code to invoke a user-defined interrupt (for example, int on x86 and swi on ARM will request a "software interrupt").
The CPU, executing in user mode, will switch to kernel mode upon seeing one of these instructions, and will jump to a predefined ISR location for that particular interrupt. The interrupt number is typically fixed, and the corresponding ISR is the system call handler for the kernel.
The kernel can inspect the user-mode registers and stack which were present at the time the interrupt was called (in a manner similar to saving all registers on the stack during a context switch), and obtain the system call arguments from there.
Ok i think i found the answer (at least i think so) at
questions about kernel space
1.The c library routine is in user address space; then how can it get the address of the interrupt service routines. Are interrupt service
routines predefined(on boot up) in physical memory?.
The ISR location is predefined as answered by nneonneo above.
2.Even if somehow the ISR routine is called how does the address space change? I mean before we start the execution of ISR how will the 'page
table base register' change to point to kernel's page table. If the
'C' routine does it then how does it know the address of Kernel's page
table?
There is no change in address space as the kernel space is essentially same as users (just the difference in protection level)

For arm Linux, could threads in user space access virtual address of Kernel space?

Virtual memory is split two parts. In tradition, 0~3GB is for user space and 3GB~4GB for kernel space.
My question:
Could the thread in user space access memory of kernel space?
For ARM datasheet, the access attribution is in the charge of domain access control register. But in kernel source code,the domain value in page table entry of user space virtual memory is same as kernel space's page table entry.
In fact, your application might access page 0xFFFF0000, as it contains the swi-handler and a couple of other userspace-helpers. So no, the 3/1 split is nothing magical, it's just very easy for the kernel to manage.
Usually the kernel will setup all memory above 3GB to be only accessible by the kernel-domain itself. If a driver needs to share memory between user and kernel-space it will usually provide an mmap interface, which then creates an aliased mapping, so you have two virtual addresses for the same physical address. This only works reliably on VIPT-Cache systems or with a LOT of careful explicit cache flushing. If you don't want this you CAN hack the kernel to make a chunk of memory ABOVE the 3G-split accessible to userspace. But then all userspace applications will share this memory. I've done this once for a special application on a armv5-system.
Userspace code getting Kernel memory? The only kernel that ever allowed that was DOS and its archaic friends.
But back to the question, look at this example C code:
char c=42;
*c=42;
We take one byte (a char) and assign it the numeric value 42. We then dereference this non-pointer, which will probably try to access the 42nd byte of virtual memory, which is almost definitely not your memory, and, for the sake of this example, Kernel memory. guess what happens when you run this (if you manage to hold the compiler at gunpoint):
Segmentation fault
Linux has memory protection like any modern operating system. If you try to access the memory of another process, your process will be terminated before it can do anything (other things I'm not so sure about happen with debuggers though). Even if that memory was that of another Userland process, you would still get terminated. I'm almost sure that root programs can't access other programs memory, or Kernel memory. The only way to access Kernel memory is to be part of the Kernel, or indirectly through the kernel's cooperation.

Resources