As we all know, a user program can notify the kernel to execute the system call through the library function. Because it is executed in the kernel space, every step must be very careful, the system crashes at any time because of wrong operations.
System calls must carefully check whether all their parameters are valid and valid. For example, system calls related to file IO must check whether the file descriptor is valid. The process-related function must check whether the provided PID is valid. Each parameter must be checked to ensure that they are valid and correct. The process should not allow the kernel to access resources that are not authorized to access.
The most important check is to check whether the pointer provided by the user is valid. Imagine if a process can pass a pointer to the kernel without checking, then it can give a pointer that has no access permissions at all, cheat the kernel to copy data that is not allowed to be accessed by it. Before receiving a user space pointer, the kernel must ensure that:
1. The memory area pointed to by the pointer belongs to the user space. The process must not spoof the kernel to read data in the kernel space.
2. The memory area pointed to by the pointer is in the address space of the process. The process must not spoof the kernel to read data from other processes.
3. For read, the memory should be marked as readable; for write, the memory should be marked as Writable; for executable, the memory is marked as executable. The process must not bypass the restrictions on memory access.
The kernel provides two methods to complete required checks and to copy back and forth data between the kernel space and the user space. Note that the kernel cannot rashly accept pointers from user space at any time! One of the two methods must be used frequently.
To write data to the user space, the kernel provides copy_to_user (), which requires three parameters. The first parameter is the destination memory address of the process space, the second is the source address of the kernel space, and the Data Length (in bytes) to be copied in the third parameter ).
To read data from the user space, the kernel provides copy_from_user (), which is similar to copy_to_user. This function copies the data at the location specified by the second parameter to the location specified by the first parameter. The copied data length is specified by the third parameter.
If the execution is successful, 0 is returned. If the execution fails, the system returns the standard-efault.
The following is a demo provided in Linux kernel design and implementation. This is an example of how to use it without value.
Syscall_define3 (silly_copy, unsigned long *, SRC, unsigned long *, DST, unsigned long Len) {/* kernel space address */unsigned long Buf; /* Copy SRC from the user address space to Buf */If (copy_from_user (& Buf, SRC, Len) Return-efault; /* copy the Buf to the DST */If (copy_to_user (DST, & Buf, Len) in the user address space) Return-efault; /* return the copied data volume */return Len ;}
It implements the function of using the kernel space as a transit, copying the source address data in the user space to the destination address in the user space, as shown in: