Linux kernel space protection

Source: Internet
Author: User


After reading the Linux code, I feel that the kernel memory protection is not very good, I also feel that some of you do not understand it correctly (the Linux code looks different from the actual one ), so 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. We recommend that you read: Linux kernel management overview. Two sets of segment descriptors are set up when a process is created in Linux. h has instructions # ifndef _ asm_segment_h # DEFINE _ kernel_cs 0x10 # DEFINE _ kernel_ds 0x18 # DEFINE _ user_cs 0x23 # DEFINE _ user_ds 0x2b # endif one for kernel code, one is used 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 can think about some pointer parameters that you call to 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 pointer validity check passed by user calls is implemented, the pointer provided by user Parameters cannot point to the system space. In this way, you only need to call these functions when writing the kernel code to implement the protection of the kernel space, which is more 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, the copy functions do not mean that the user space and the kernel space need to be switched to be copied, in this regard, many people do not really understand this point. 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 is the related content of several files: file uaccess. h: # define make_mm_seg (s) (seconds) {(s)}) # define kernel_ds make_mm_seg (0 xffffffffff) # 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) // sets the user space range yrg file processor. h: typedef struct {unsigned long seg;} mm_segment_t; file page. h: Include # d Efine _ page_offset (page_offset_raw) # define page_offset (unsigned long) _ page_offset) file detail: # 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 // This clearly configures the size of user space and system space. yrg let's see get_ds (), get_fs (), set_fs (), and other functions may not be the same thing 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. Do you want to take a closer look at the preceding set_fs (x) call, 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 following code to clarify the functions of the set_fs. -> Filename is in our kernel spaceunsigned 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... */Well, the principle is over, and the code can be understood. Let's look at this kind of programming? In fact, this programming is obviously not good. The disadvantages are as follows: 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. 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. In fact, there is 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. During kernel calling, this variable can be easily referenced to detect the call parameters of user code, use another kernel global variable to distinguish whether the program runs in the kernel or user State, if you call the system function again in the kernel state, you do not need to check whether the parameters called by the system are between the inner core and the user space. This avoids the trouble of modifying the global variable.

Previous Article: Five risks in Linux socket programming
Next article: Linux static/Dynamic Link Library Creation and use

 

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.