Linux kernel space protection

Source: Internet
Author: User
/* Arrange for userspace references to be interpreted as kernel
* Pointers. That way we can pass a kernel pointer to a routine
* That expects a _ User pointer and it will work okay .*/
Set_fs (get_ds ());

# Define kernel_ds 0x00000000
# Define user_ds task_size

# Define get_ds () (kernel_ds)
# Define get_fs () (current_thread_info ()-> addr_limit)

Static inline void set_fs (mm_segment_t FS)
{
Current_thread_info ()-> addr_limit = FS;
Modify_domain (domain_kernel, FS? Domain_client: domain_manager );
}

Zz

Http://www.enet.com.cn/article/2004/0729/A20040729328800.shtml

After reading the Linux code, I feel that the kernel memory protection is not very good, and I also feel that some people do not understand it correctly (mainly because the Linux code looks different from the actual one ), in this article, I will talk about the Linux kernel space protection and the code views on user space and system space data transmission. note that I am talking about the i386 architecture. For other architectures, you can check the corresponding code and cannot guarantee whether the result is as I said.
Two sets of segment descriptors are set up when a process is created in Linux, which are described in the file segment. h.

# Ifndef _ asm_segment_h
# DEFINE _ asm_segment_h

# DEFINE _ kernel_cs 0x10
# DEFINE _ kernel_ds 0x18

# DEFINE _ user_cs 0x23
# DEFINE _ user_ds 0x2b

# Endif

One for kernel code and one for user code. when running the kernel code, you can directly access the user space by using the segment description symbol of the kernel. However, when running the user code, the user segment descriptor cannot access the kernel space, which is a protection mode, the specific code is not introduced. if you don't understand it, you have to read some books about the protection mode.
When the user code calls the system function, the program enters the system kernel code, and the descriptor has been switched to the kernel descriptor. In this case, you can directly access the user space or the kernel space, the parameter data transmission between the two is also very simple, and can be directly copied. But all users who have read the Linux code know that the user space and kernel space parameter transfer in the system function code are not directly copied. Why? You may think that some pointer parameters called by the user can point to the kernel space. If you do not check them and copy them directly, the user space code can read and write the kernel space through the system call, this is obviously not allowed. Therefore, some unified functions are used in the kernel code:
Copy_from_user/copy_to_user and _ generic_copy_from_user/_ gerneric_copy_to_user
In these functions, the validity of pointer passed by user calls is detected. Pointers provided by user Parameters cannot point to system space, in this way, when writing the kernel code, you only need to call these functions to implement the protection of the kernel space, which is also convenient to write. This reminds everyone that when writing the kernel code, do not copy the parameters of user space and kernel space directly, in fact, those copy functions do not mean that users need to switch between the empty room and the kernel space before copying. I don't really understand this.
Let's take a closer look at how the copy functions implement kernel space protection. It turns out that a user space range is saved in the process data structure of each process, current-> addr_limit, because the kernel space is on the user space, therefore, you only need to check whether the space accessed by passing parameters is smaller than or equal to this range. The following content is related to several related files:

File uaccess. h:
# Define make_mm_seg (s) (mm_segment_t) {(s )})

# Define kernel_ds make_mm_seg (0 xffffffff)
# Define user_ds make_mm_seg (page_offset)

# Define get_ds () (kernel_ds)
// Obtain the kernel space range yrg
# Define get_fs () (current-> addr_limit)
// Obtain the user space range yrg
# Define set_fs (x) (current-> addr_limit = (x ))
// Set the user space range yrg

File processor. h:
Typedef struct {
Unsigned long seg;
} Mm_segment_t;

File page. h:
Include

# DEFINE _ page_offset (page_offset_raw)

# Define page_offset (unsigned long) _ page_offset)

File page_offset.h:
# Include
# Ifdef config_1gb
# Define page_offset_raw 0xc0000000
# Elif defined (config_2gb)
# Define page_offset_raw 0x80000000
# Elif defined (config_3gb)
# Define page_offset_raw 0x40000000
# Endif
// You can configure the user space and system space size.

Let's take a look at the get_ds (), get_fs (), set_fs () and other functions that you just thought about? They seem to be accessing or setting a segment, but they only access or set a process variable.

You can see that some of the parameters passed by the copy function can only point to the user space. What should we do if the kernel code calls some functions of the system, because all the parameters are in the kernel space at that time. Take a closer look at whether there is a set_fs (x) Call above, that is, to set the user space limit for the call, as long as the temporary setting of the user space limit to the kernel space range, after the call is completed, it will be restored. Let's take a look at the code below to get a clear picture of the functions of the set_fs.

-> Filename is in our kernel space

Unsigned long old_fs_value = get_fs ();

Set_fs (get_ds ();/* after this we can access the user space data */
Open (filename, o_creat o_rdwr o_excl, 0640 );
Set_fs (old_fs_value);/* restore Fs ...*/

Okay, the principle is over, and we can see the code. Let's look at this kind of programming? In fact, this programming is obviously not good. Disadvantages:

1. There is no unified protection method yet, which is not good for kernel space protection. If you do not pay attention to kernel code programming, your program may break through the protection of kernel space. The kernel code editor must note that the copy functions must be used for copying user space and system space, rather than simply copying them directly.
2. the kernel code imposes a poor user space limit on system function calls. In this case, if the user space limit of the process has not been set back, if the user code of the process is run (it is unlikely), the kernel space limit is broken. In addition, if the kernel code does not care about restoring the user space limit, the kernel space protection will also become invalid.

There is actually a good way to achieve it very easily. It is to use a kernel global variable to save the user space range, which is calculated according to the configuration during startup, when the kernel is called, this variable can be easily referenced to detect the call parameters of the user code. Another kernel global variable is used to identify whether the program is running in the kernel or user State, if you call a system function in the kernel state, you do not need to check whether the system-called parameters are in the kernel space or user space. This avoids the trouble of modifying the global variable.

Kernel learning FAQ ZZ

Http://www.discuz.net/viewthread.php? Tid = 26370

4.3 how to open and operate a file in the kernel?
A. directly use open (), read (), and other systems for calling. See question 4.2.
B. Use the filp_open () function to open the file and obtain the pointer FP of struct file.
Use the pointer FP for corresponding operations. For example, you can use FP-> f_ops-> Read to read a file.
Finally, use the filp_close () function to close the file.
The filp_open () and filp_close () functions are defined in FS/open. C and in include/Linux/fs. h.
Statement.
C. Write the packaging function by yourself. You can refer to the open_exec () and kernel_read () functions in file fs/exec. C.
In http://www.linuxforum.net/forum/ .. t = & board = linuxk
& Number = 363455 & page = & view = & SB = & O = & Vc = 1 some code can be referenced.

4.4 why does the efault error occur when reading and writing files in the kernel?
A. functions such as read () and write () provided by the Kernel File System are expected to serve user-state programs,
Therefore, it verifies that the read/write buffer does not exceed the user space limit, that is, 0xc000 0000. But in the kernel
To read and write files, the buffer address in the kernel will exceed 0xc000 0000.
B. Obtain the current FS: mm_segment_t old_fs = get_fs ();
Set the current FS as the kernel FS: set_fs (kernel_ds );
After reading and writing the file, restore the original FS: set_fs (old_fs );
Set_fs (), get_fs () and other related macros are defined in the File Include/ASM/uaccess. h.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.