In the IA32 operating system, segments are divided into four privilege levels, which are 0-3, sometimes we call ring0-ring3, in which the smaller the value, the higher the privilege level. As shown in the following figure:
In the graph, the privilege level of the segment where the core code and data are located is higher, generally at ring0, while the privilege level of the segment where the user program is located is lower, generally at ring3. Conventional protection errors occur when low-privileged tasks attempt to access high-privileged segments without permission.
How does the processor differentiate the privilege level of the segment and protect it? This has to mention CPL, DPL and RPL. But before we start, we need to understand consistent and inconsistent code segments.
Consistent and inconsistent code segments
In the operating system, we have some high-privileged code that we want to be accessed by low-privileged programs, such as library functions, so we put these high-privileged code in a section called consistent code segment. And some high privileged code, we don’t want low privileged programs to access, so we put them in a section called inconsistent code segment. Specifically, when a call or JMP directive is transferred to another segment (i.e., access to another segment), we can access it when the target of the transfer is a consistent segment with higher priority, but the current privilege level will be continued; when the target of the transfer is a non-consistent segment with higher priority. At this point, access will cause a general protection error (unless the call gate or task gate is used).
Consistent code segment: The segment where the code shared by the system (high privilege level) to a program with low privilege level is located. There are two main restrictions:
- High-privileged programs cannot access low-privileged data
- Low-privileged programs can access high-privileged code, butPrivilege level will not changeOr maintain the privilege level of low-privileged programs
Inconsistent code segments: To avoid being accessed by low-privileged programs and protect the code segments, there are a major limitation:
- Only peer-to-peer access is allowed
- In addition, data segments are inconsistent
The following rules are followed:
CPL is called Current Privilege Level. As its name implies, CPL represents the privilege level of tasks and programs currently executed. It is stored in bits 0 and 1 of CS and ss.NormallyCPL is equal to the privilege level of the segment in which the code resides. When the program moves to a different segment, the processor changes the value of the CPL.
However, when accessing a consistent code segment, it does not change the CPL. As stated in the consistent code segment, a consistent code segment can be accessed by a lower privilege level program, but it does not change the privilege level, so it does not change the CPL, which is a “non-general situation” in contrast to the “general situation” that has been coarsened above.
DPL is the Descriptor Privilege Level, which represents the privilege level of a segment or gate. It is stored on the DPL field in the segment descriptor or gate descriptor property.
When the current code segment attempts to access a segment or gate, DPL will be compared with CPL and RPL of segment or gate selector. For different types of segment or gate, the comparison rules are different, as follows:
- Data segment: If a data segment is accessed, DPL represents the lowest privilege level for accessing this segment, that is, only CPL <= DPL (numerically) can have access.
- Inconsistent code segments (without calling gates): DPL represents the privilege level for accessing this segment. That is, only DPL = RPL has access.
- Call gate: DPL specifies the minimum privilege level at which tasks and programs currently executed can access this call gate, i.e. CPL <= DPL
- Consistent and inconsistent code segments (accessed using call gates): DPL specifies the highest privilege level for accessing this segment. That is, only CPL >= DPL has access.
- TSS: DPL specifies the lowest privilege level for accessing this TSS.
To sum up, it is:
- In data segments, call gates and TSS, DPL represents the lowest privilege level. Access requirements: CPL <= DPL
- When non-persistent code segments accessed by call gates are not used, access requirements: CPL = DPL
- In consistent code segments and inconsistent code segments accessed by calling gates, DPL represents the highest privilege level, and access requirements are: CPL >= DPL
RPL is called Requested Privilege Level. RPL is stored on the 0th and 1st bit of segment selector. As we mentioned above, when one segment accesses another, the rules of comparison between CPL and DPL are not enough. The processor also checks RPL to determine whether another segment can be accessed.
Operating systems often use RPL to avoid low-privilege applications accessing data in high-privilege segments. Even if the segment requesting access has sufficient privilege levels, if RPL is not enough, RPL will play a decisive role when the value of RPL is larger than CPL. That is to say, only when the CPL and RPL are smaller than the DPL of the data segment to be accessed can the data segment be accessed.
- The Realization of an Operating System