Intel® ISA Extensions
Use hardware-based isolation and memory encryption to provide more code protection in your solutions.

RPL, CPL and DPL question

Victor_K_
Beginner
4,328 Views

Good day.

In Intel SDM vol. 3 / 5.6 "PRIVILEGE LEVEL CHECKING WHEN ACCESSING DATA SEGMENTS" we can read:

Before the processor loads a segment selector into
a segment register, it performs a privilege check (see Figure 5-4) by comparing the privilege levels of the currently
running program or task (the CPL), the RPL of the segment selector, and the DPL of the segment’s segment
descriptor. The processor loads the segment selector into the segment register if the DPL is numerically greater
than or equal to both the CPL and the RPL. Otherwise, a general-protection fault is generated and the segment
register is not loaded.

So, if we have a code which runs at level 3, we can't do

mov eax,28h ;points to descriptor with DPL=0
mov DS,eax

because it would lead to #GP, as the CPL=3, RPL=0, DPL=0.

But then in manual we found this:

It is important to note that the RPL of a segment selector for a data segment is under software control. For
example, an application program running at a CPL of 3 can set the RPL for a data- segment selector to 0.

How it is possible?
Or I misunderstand something?

Thanks in advance.

0 Kudos
1 Solution
Konstantin_B_
Novice
4,328 Views

Victor K. wrote:

Please, correct me if I'm wrong:

- words "is under software control" means "client" can pass (by stack, common register or any other way, but not in the segment register) selector to the "server" with any RPL
- "client" can't succesfully execute (assume CPL=3, selector 10h points to descriptor with DPL=0)
mov ax,10h
mov DS,ax
because it would lead to #GP.

Yes, client cannot perform such load, but this is not the point I tried to make.  It is more interesting what happens at the server side, i.e. when a code  executing at the privilege higher than the client privilege, operates on the clent-provided pointers.

RPL is under software control in the sense that software can arbitrary modify the RPL value at wish.  Not all RPL values are useful, and not all RPL values can be specified when performing segment load to end in successful load.  The two sets are not necessary same.  On the other hand, the set of valid descriptor indexes is not under software control, it is determined by the content of the GDT and LDT, which are managed by OS.

Victor K. wrote:

To be more specific: for me "RPL is under software control" means I can freely manipulate RPL when loading the segment register. When I pass selector to the "server" by stack, it is not a segment register. It's just piece of data with any meaning. In this sense, we could say "selector index is under software control". It could be null, it could be out of GDT/LDT limit, it could be anyting.

And related question: does CPU performs CPL/RPL/DPL checks only at selector loading stage, or does also at stage of memory access?
For example, assume CPL=3, DS is already loaded (by someone with CPL=0) with descriptor's selector with DPL=0. Would "mov eax,[eax]" lead to #GP?

Privilege checks are performed only at the segment registers load time.  If more privileged code returns to the less privileged state and leaks high-privileged descriptor in some segment register, then it opens the access to the data.  For this reason, regular inter-privilege return methods like IRET or RET invalidate content of segment registers that point to higher privileged descriptors (and really invalidate the content of descriptor caches associated with that segment).

View solution in original post

0 Kudos
10 Replies
Victor_K_
Beginner
4,328 Views

Seems I'm at wrong forum. Can somebody tell me, where I should ask about common CPU features? I mean, like this topic subject or stack operation clarification, common instruction set etc

Thanks.

0 Kudos
SergeyKostrov
Valued Contributor II
4,328 Views

When an Intel CPU is in protected mode it is done as follows:

...
; Initialize all segment registers to 10h (entry #2 in the GDT)

   mov ax,10h   ; entry #2 in GDT
   mov ds,ax    ; ds = 10h
...

 

0 Kudos
SergeyKostrov
Valued Contributor II
4,328 Views
>>Can somebody tell me, where I should ask about common CPU features? Victor, this is the right place to ask questions about CPU features.
0 Kudos
Victor_K_
Beginner
4,328 Views

Thanks for the answer, Sergey!

But how it is possible when entry #2 descriptor has DPL=0 and CPL=3? It would lead to #GP, isn't it?

I'm confused by words "the RPL of a segment selector for a data segment is under software control. For example, an application program running at a CPL of 3 can set the RPL for a data- segment selector to 0".

0 Kudos
Konstantin_B_
Novice
4,328 Views

Victor K. wrote:

Thanks for the answer, Sergey!

But how it is possible when entry #2 descriptor has DPL=0 and CPL=3? It would lead to #GP, isn't it?

I'm confused by words "the RPL of a segment selector for a data segment is under software control. For example, an application program running at a CPL of 3 can set the RPL for a data- segment selector to 0".

#GP is the valid and sometimes desired outcome. The later text in the SDM Vol. 3 section 5.6  you cited gives the useful hint as to why, see the paragraph about impersonalization right before the citation. More, after your citation, there is a note about 'dangers' of using RPL 0 by the privileged code and suggestion to use the ARPL instruction.

RPL allows more privileged code to work with the far pointers supplied by the potentially untrusted code in safer way.  Imagine a code executing at say CPL 1 (server) which might take pointers from the code executing at CPL 1, 2, or 3 (client).  In these cases, you do not want for the client code with CPL 2 or 3 to somehow guess a valid DPL 1 selector index and pass it to the server.  Or rather, you want the server to not allow to trick itself into writing into the memory described by corresponding descriptor, you only want it to write a segment which is also accessible to the client.

So what is supposed to happen, with the IA32 protection model, is that server sets RPL to the CPL of the client and then #GP catches invalid accesses at the moment the selectors are loaded into segment registers.All this happens automatically (#GP->typical abort, or whatever proper reaction is), instead of using ARPL or other explicit methods.

Of course, nobody uses the mechanism now, but this is how it was designed to be used.

0 Kudos
SergeyKostrov
Valued Contributor II
4,328 Views
>>...But how it is possible when entry #2 descriptor has DPL=0 and CPL=3? It would lead to #GP, isn't it? Victor, In case of DPL=0 and CPL=3 did you try to do it using PUSH and POP instructions? An example in Post #3 is from a real piece of codes. It does DS register initialization after a CPU is switched to protected mode and a privilege level is 0.
0 Kudos
Victor_K_
Beginner
4,328 Views

Sergey, I know my english is terrible. But what relation with push/pop instructions at all? Segment register's loading mechanism is same for "pop Sreg" and "mov Sreg,smth" instructions. My question is about ambiguos manual statements.

2Konstantin
My respect for fullfill answer. Please, correct me if I'm wrong:

- words "is under software control" means "client" can pass (by stack, common register or any other way, but not in the segment register) selector to the "server" with any RPL
- "client" can't succesfully execute (assume CPL=3, selector 10h points to descriptor with DPL=0)
mov ax,10h
mov DS,ax
because it would lead to #GP.

To be more specific: for me "RPL is under software control" means I can freely manipulate RPL when loading the segment register. When I pass selector to the "server" by stack, it is not a segment register. It's just piece of data with any meaning. In this sense, we could say "selector index is under software control". It could be null, it could be out of GDT/LDT limit, it could be anyting.

And related question: does CPU performs CPL/RPL/DPL checks only at selector loading stage, or does also at stage of memory access?
For example, assume CPL=3, DS is already loaded (by someone with CPL=0) with descriptor's selector with DPL=0. Would "mov eax,[eax]" lead to #GP?

0 Kudos
Konstantin_B_
Novice
4,329 Views

Victor K. wrote:

Please, correct me if I'm wrong:

- words "is under software control" means "client" can pass (by stack, common register or any other way, but not in the segment register) selector to the "server" with any RPL
- "client" can't succesfully execute (assume CPL=3, selector 10h points to descriptor with DPL=0)
mov ax,10h
mov DS,ax
because it would lead to #GP.

Yes, client cannot perform such load, but this is not the point I tried to make.  It is more interesting what happens at the server side, i.e. when a code  executing at the privilege higher than the client privilege, operates on the clent-provided pointers.

RPL is under software control in the sense that software can arbitrary modify the RPL value at wish.  Not all RPL values are useful, and not all RPL values can be specified when performing segment load to end in successful load.  The two sets are not necessary same.  On the other hand, the set of valid descriptor indexes is not under software control, it is determined by the content of the GDT and LDT, which are managed by OS.

Victor K. wrote:

To be more specific: for me "RPL is under software control" means I can freely manipulate RPL when loading the segment register. When I pass selector to the "server" by stack, it is not a segment register. It's just piece of data with any meaning. In this sense, we could say "selector index is under software control". It could be null, it could be out of GDT/LDT limit, it could be anyting.

And related question: does CPU performs CPL/RPL/DPL checks only at selector loading stage, or does also at stage of memory access?
For example, assume CPL=3, DS is already loaded (by someone with CPL=0) with descriptor's selector with DPL=0. Would "mov eax,[eax]" lead to #GP?

Privilege checks are performed only at the segment registers load time.  If more privileged code returns to the less privileged state and leaks high-privileged descriptor in some segment register, then it opens the access to the data.  For this reason, regular inter-privilege return methods like IRET or RET invalidate content of segment registers that point to higher privileged descriptors (and really invalidate the content of descriptor caches associated with that segment).

0 Kudos
Victor_K_
Beginner
4,328 Views

Thank you, Konstantin. Problem is solved now :)

0 Kudos
SergeyKostrov
Valued Contributor II
4,328 Views
>>Before the processor loads a segment selector into a segment register, it performs a privilege check (see Figure 5-4) >>by comparing the privilege levels of the currently running program or task (the CPL), the RPL of the segment selector, >>and the DPL of the segment’s segment descriptor. The processor loads the segment selector into the segment >>register if the DPL is numerically greater than or equal to both the CPL and the RPL. Otherwise, a general-protection >>fault is generated and the segment register is not loaded. Simply to note that It translates to: ... ( DPL >= Max( RPL, CPL ) ) ? ( Access Allowed ) : ( Access Not Allowed / GPE ) Where, DPL - Descriptor Privilege Level CPL - Current Privilege Level RPL - Requested Privilege Level GPE - General Protection Exception ...
0 Kudos
Reply