Why do you have to use copy_to_user()/copy_from_user() to access user space from the kernel?
I’m curious, because I got a kernel panic after trying to access memory directly (then I found these functions).
2 Answers 2
These functions do a few things:
- They check if the supplied userspace block is entirely within the user portion of the address space ( access_ok() ) — this prevents userspace applications from asking the kernel to read/write kernel addresses;
- They return an error if any of the addresses are inaccessible, allowing the error to be returned to userspace ( EFAULT ) instead of crashing the kernel (this is implemented by special co-operation with the page fault handler, which specifically can detect when a fault occurs in one of the user memory access functions);
- They allow architecture-specific magic, for example to ensure consistency on architectures with virtually-tagged caches, to disable protections like SMAP or to switch address spaces on architectures with separate user/kernel address spaces like S/390.
@ComtriS: I’m not sure what you mean by «allowed», but if you’re getting a kernel panic then either you must not have checked the page permissions or not disabled some architecture-specific protection. Note that checking the page permissions and then accessing the pages is going to be racy.
is it only for security check (including checking mmu table entry is valid)? if I use just memcpy instead of copy_from/to_user function, can it just run ok in some cases? I want to know if the copy_from/to_user contains address translation(using software) function.
@ChanKim: It depends on the architecture (see the third point in the answer). For example, SMAP is going to stop you on x86-64 with a modern processor.
yes, I can understand the STAC, CLAC commands to access user space. but isn’t the user address ‘value’ virtual address handed from user process (different address space)? how can the kernel access the memory area pointed to by the ‘user virtual address’ with its kernel mmu table? shouldn’t there be address ‘value’ translation using user process’s page table? I looked into the kernel source but it’s a little complex for me to follow.. 🙂
@ChanKim: Some architectures (e.g. S/390) do use completely separate address spaces for the kernel and user space. However, on others like x86-64 and arm the user addresses for the current process are mapped into the kernel page tables (on x86-64, the kernel address space has all the upper bits of the addresses as 1, and the user part has those upper bits as 0). Without the Spectre/Meltdown countermeasures active, the page table isn’t even changed between kernel and user mode — it only changes when switching between processes.
Those functions check whether the memory is accessible. If the kernel attempts to directly access a non-accessible address, it will panic. But in addition, the kernel and user address spaces may be different . a valid address in the user address space may not be accessible in the kernel, and if it is it may point to kernel stuff rather than user stuff.
On a historical note: once upon a time there were operating systems in which the kernel was designed to be part of the user address space, and in those systems the kernel could always access user space directly. There may still be such systems, but modern linux isn’t one. The user process’s memory being part of the kernel address space is always an option for the implementation, of course, and that can make copy_to_user and copy_from_user a lot faster.
How does copy_from_user from the Linux kernel work internally?
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?
4 Answers 4
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.
Thank You,i was sure bout direct access by the kernel,so basically i guess it does a prior check on the pointer/address that is passed onto it so as to check if some invalid address is not passed onto the function i mean to say address belonging to some other user space process. anyway i did not know bout the memory protection thing that you have mentioned. So my DOubt is wht bout in the case of copy_to_user. since the user space is passed an address within the kernel space VM. how does the user space acccess it..or is it that the kernel maps that address to some user space address
@Santi1986: copy_to_user() works in exactly the same way, except that the source and destination addresses are swapped — it reads from kernel addresses and writes to userspace addresses. The only check that is done in both is that the userspace address really is below the kernel/user split; there is no need to check for addresses belonging to other user processes, because copy_*_user() are called only in process context, which means that all addresses are either kernel addresses or belong to the current process.
Thank you for your time i just browsed though the code and found out this kernel checks the validity of the pointers through access_ok),basically function copy__user is called which internally uses this function __copy__user_inatomic which finally calls __copy*_user_ll, which does the actuall copying and also the PAGES ARE PINNED PRIOR COPYING. if the entire data is not copied its padded with zero(by the len passed to the call)
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).
Why does the kernel use the copy_to_user() function?
Why does the kernel use the copy_to_user function? Couldn’t it just directly operate on data in the user space?
2 Answers 2
kernel and user-space applications have different address spaces, so copying to user space require an address space change. Each process has its own (user) address space.
Also, kernel should never crash when copying to user space, so the copy_to_user function probably checks that the destination address is valid (perhaps that address should be paged-in, e.g. from swap space).
If a given kernel were written for only one architecture this may or may not be a reasonable choice.
There are a lot of considerations that may vary per architecture and therefore require some sort of polymorphic operation.
- protection . the kernel may have too many or too few access rights, either way may require extra code on a given target
- address space . the user space and kernel space may overlap, and so a target-specific solution or temporary map would be needed
- page fault management . access to the user space can fault and this needs to be either avoided or allowed. Confining the access to a given specific place allows either extra setup or identification of the reason for the fault.
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.14.43533
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.