Search code examples
x86intelmemory-segmentationprivilege

Privilege level checking when accessing code segment


I'm trying to understand some specifics about about the intel x86 architecture. I have not yet really understood the call gate mecanism, but without it, for accessing a non conformant code segment it's DPL must be equal to the CPL.

I do understand that it is important in case of DPL < CPL but why in the case DPL > CPL it is forbidden ? I mean the CPL could remain unchanged after the jump if we wanted to keep the same privilege level, and if we wanted to lower our privilege we could use the RPL .


Solution

  • As a general rule when you access a code segment directly you can only do that for segments with the same privilege.
    This is what the Non Conforming Code Segments (NCCS) are used for.
    Intel made has the favor of introducing also Conforming Code Segment (CCS) that can be accessed by less privileged applications (in case the kernel need to share some code without elevating the privilege of the caller).

    Accessing a code segment directly never change the current privilege, the CPL of the target code is the CPL of the caller.

    The RPL also takes no role. It is ignored for CCS and must be less or equal to the caller CPL for NCCS (this is likely a side effect).

    The rules are:

    NCCS
    1. Caller CPL must be equal to descriptor DPL (Same privilege) 2. The target code will be run with CPL equal to the caller CPL regardless of the RPL used in the selector. 3. The selector RPL must be less or equal to the caller CPL.

    CCS
    1. Caller CPL must be greater or equal to descriptor DPL (less privileged) 2. The target code will be run with CPL equal to the caller CPL regardless of the RPL used in the selector.

    As you can see accessing directly the code segment doesn't change the CPL (and there is no stack change).

    To change privilege (CPL) Intel introduced Call Gates. With CG, as with Data Segments, the RPL let you impersonate a less privileged program.
    If a CG as DPL=2 (and the target selector also have DPL>=2) and your code has CPL=0, you can choose to perform the call as a user mode application with CPL=3 (thereby not gaining the access) or as a kernel component with CPL=2 (gaining the access but without the possibility to call other more privileged code segments).