Question on RPL
Question on RPL
Hi, all
I am rather confused over the purpose of RPL. IMHO, CPL and DPL should be able to fulfill all the functions that is designated to RPL. Anyway, a Ring 3 process can always change RPL of the selector it uses since it has full cover over this.
Intel Manual talks about its purpose in a short paragraph as quoted below but it couldn't convince me. Rather I feel they are suggesting there are alternatives to RPL with software censorship ways.
"Operating-System procedures typically use the RPL to prevent less privilleged application programs from accessing data located in more privileged segments. When an operating-system procedure (the called procedure) receives a segment selector from an application program (the calling procedure), it sets the segment selector's RPL to the privilege level of the calling procedure. Then, when the operating system uses the segment selector to access its associated segment, the processor performs privilege checks using the calling procedure's privilege level (stored in RPL) rather than the numerically lower privilege level (the CPL) of the operating system procedure. The RPL thus insures that the operating system does not access a segment on behalf of an application program unless that program itself has access to the segment"
What I am trying to find out is how an OS utilizes RPL for its purposes? Can anyone give me some clue how it is used in your designed OS? Thanks in advance.
Best regards,
Cody
I am rather confused over the purpose of RPL. IMHO, CPL and DPL should be able to fulfill all the functions that is designated to RPL. Anyway, a Ring 3 process can always change RPL of the selector it uses since it has full cover over this.
Intel Manual talks about its purpose in a short paragraph as quoted below but it couldn't convince me. Rather I feel they are suggesting there are alternatives to RPL with software censorship ways.
"Operating-System procedures typically use the RPL to prevent less privilleged application programs from accessing data located in more privileged segments. When an operating-system procedure (the called procedure) receives a segment selector from an application program (the calling procedure), it sets the segment selector's RPL to the privilege level of the calling procedure. Then, when the operating system uses the segment selector to access its associated segment, the processor performs privilege checks using the calling procedure's privilege level (stored in RPL) rather than the numerically lower privilege level (the CPL) of the operating system procedure. The RPL thus insures that the operating system does not access a segment on behalf of an application program unless that program itself has access to the segment"
What I am trying to find out is how an OS utilizes RPL for its purposes? Can anyone give me some clue how it is used in your designed OS? Thanks in advance.
Best regards,
Cody
- Colonel Kernel
- Member
- Posts: 1437
- Joined: Tue Oct 17, 2006 6:06 pm
- Location: Vancouver, BC, Canada
- Contact:
Re:Question on RPL
It's hard to explain directly, but I can explain by analogy. The problem is that my analogy is also really complex.
If you've ever done any programming involving the Win32 security APIs, you might have come across the concept of "impersonation". Basically, a thread in a server process temporarily assumes the identity and permissions associated with a client thread so that any actions it takes on behalf of the client are subject to the client's own permissions. RPL is basically the same thing, only at a hardware level -- the OS uses it to "impersonate" the client process' privilege level for the purposes of accessing some segment on its behalf.
Does this make sense?
If you've ever done any programming involving the Win32 security APIs, you might have come across the concept of "impersonation". Basically, a thread in a server process temporarily assumes the identity and permissions associated with a client thread so that any actions it takes on behalf of the client are subject to the client's own permissions. RPL is basically the same thing, only at a hardware level -- the OS uses it to "impersonate" the client process' privilege level for the purposes of accessing some segment on its behalf.
Does this make sense?
Top three reasons why my OS project died:
- Too much overtime at work
- Got married
- My brain got stuck in an infinite loop while trying to design the memory manager
Re:Question on RPL
I'll try to explain best as possible, but I know other people would do better.
CPL is your CS privilege level, meaning your current privilege level in which ring your currently running. Inorder for you to jump into differnt rings you need to request for the privilege, this is done by applying the RPL to the target selector. Whether or not the request is privileged also depends on whether if your using conforming or non-conforming descriptors for code segments specifically. In conforming, your restricted to access the same CPL which you need to request the same current privilege level (RPL=CPL), while any other privilege levels will not be allowed. In non-conforming you may request (RPL) to run numerically equal or higher then your current CPL. This allows the operating system at the CPL0 to yeild to CPL1, CPL2 or CPL3 but when your in CPL3 cannot run CPL0, CPL1 or CPL2 without using gates, this also applies to data segments not just code segments. So really, the RPL really just turns into CPL once the privilege checks are made successfully.
CPL is your CS privilege level, meaning your current privilege level in which ring your currently running. Inorder for you to jump into differnt rings you need to request for the privilege, this is done by applying the RPL to the target selector. Whether or not the request is privileged also depends on whether if your using conforming or non-conforming descriptors for code segments specifically. In conforming, your restricted to access the same CPL which you need to request the same current privilege level (RPL=CPL), while any other privilege levels will not be allowed. In non-conforming you may request (RPL) to run numerically equal or higher then your current CPL. This allows the operating system at the CPL0 to yeild to CPL1, CPL2 or CPL3 but when your in CPL3 cannot run CPL0, CPL1 or CPL2 without using gates, this also applies to data segments not just code segments. So really, the RPL really just turns into CPL once the privilege checks are made successfully.
Re:Question on RPL
Hi, ColonelColonel Kernel wrote: If you've ever done any programming involving the Win32 security APIs, you might have come across the concept of "impersonation". Basically, a thread in a server process temporarily assumes the identity and permissions associated with a client thread so that any actions it takes on behalf of the client are subject to the client's own permissions. RPL is basically the same thing, only at a hardware level -- the OS uses it to "impersonate" the client process' privilege level for the purposes of accessing some segment on its behalf.
Does this make sense?
Thanks very much for your help!
I happened to be a Win32 Application Programmer before I joins in BIOS industry so what you talks about sounds familiar to me.
I agree that RPL can help in this case, but the problem is still the same, the server thread can always tell the client thread's true privilege from its CS's CPL pushed on the stack when switching from client thread context to server thread context. Why should it ever bother with RPL?
What's more, the client thread can have control over the selector's RPL I think. There is nothing to stop a determined client thread from setting its target selector's RPL to Ring 0, right?
Please correct me if I fail to understand you in the right way. ;D
Best regards,
Cody
Re:Question on RPL
Hi, RyuRyu wrote: I'll try to explain best as possible, but I know other people would do better.
CPL is your CS privilege level, meaning your current privilege level in which ring your currently running. Inorder for you to jump into differnt rings you need to request for the privilege, this is done by applying the RPL to the target selector. Whether or not the request is privileged also depends on whether if your using conforming or non-conforming descriptors for code segments specifically. In conforming, your restricted to access the same CPL which you need to request the same current privilege level (RPL=CPL), while any other privilege levels will not be allowed. In non-conforming you may request (RPL) to run numerically equal or higher then your current CPL. This allows the operating system at the CPL0 to yeild to CPL1, CPL2 or CPL3 but when your in CPL3 cannot run CPL0, CPL1 or CPL2 without using gates, this also applies to data segments not just code segments. So really, the RPL really just turns into CPL once the privilege checks are made successfully.
Thanks for your help!
I know the theory and privilege checking mechanisms involving CPL, RPL and DPL. But they are just descriptions and none further from that. What I am trying to find out is "why"? I am trying to guess the motivation behind the introduction of RPL. The hardware guys invented this concept, they must be up to something that OS can utilize. But my current understanding indicates that they are not indispensable at all.
What's more, I am not talking about the CPL in the segment register(CS, DS,etc) but rather the RPL in the segment selector you use either to access data or initiate execution transfer (it could be selector to target code segment, target call gate, etc).
Thanks again for your help! ;D
Best regards,
Cody
Re:Question on RPL
I realise I have conforming and non-conforming all backwards again. The fix up what I said the non-conforming is the one that cannot change privilege levels. But if your searching why have RPL is the first place gots lot to do with the conforming/non-conforming thing where non-conforming doesn't cares about RPL at all.Cody wrote:
I know the theory and privilege checking mechanisms involving CPL, RPL and DPL. But they are just descriptions and none further from that. What I am trying to find out is "why"? I am trying to guess the motivation behind the introduction of RPL. The hardware guys invented this concept, they must be up to something that OS can utilize. But my current understanding indicates that they are not indispensable at all.
What's more, I am not talking about the CPL in the segment register(CS, DS,etc) but rather the RPL in the segment selector you use either to access data or initiate execution transfer (it could be selector to target code segment, target call gate, etc).
However in conforming segments RPL is used so that it determines which other privilege level to enter, while entering a less privilege will not allow you to request back to a more privilege segment. Just remember that RPL does eventually become your CPL once privileges are checked sucessfully. Or may think of it as RPL is the CPL only it was nevered been privileged checked. If you say CPL and DPL is only required then its a more nonconforming segment design, and on the other hand RPL is needed in conforming where its allowed to change privilege levels.
This may or may not what you wanted but I think chapter 4 in volume 3A (2006 PDF), specifically section 4.8 which explains transferring program controls in conforming and non-conforming would help understand.
Re:Question on RPL
Well, I admit you have to use RPL to do all those privilege switchings. The point I want to emphasis is that you can always manipulate these RPLs. You have full control over what RPL value to put into the selector, right? For example, you could:However in conforming segments RPL is used so that it determines which other privilege level to enter, while entering a less privilege will not allow you to request back to a more privilege segment. Just remember that RPL does eventually become your CPL once privileges are checked sucessfully. Or may think of it as RPL is the CPL only it was nevered been privileged checked. If you say CPL and DPL is only required then its a more nonconforming segment design, and on the other hand RPL is needed in conforming where its allowed to change privilege levels.
mov ax, sel
and ax, 0xFFFC ; to mask RPL as 0
With that said, I am more eager to know in what cases your manipulation of RPL will be futile. Currently, if you find the RPL in your selector prevents you from doing a successful switching you can always overwrite it. I am wondering when some enforcement will be carried out that renders RPL truly unshakable.
Re:Question on RPL
If that selector descriptor is DPL=3, and you set the selector's RPL=0 running in CPL=3, and also this selector is in the GDT, loading this in any segment registers will generate a GPF, Bochs will output (RPL & CPL must be <= DPL). If in the same circumstance but the selector is within LDT, from what I tested, theres no checks made and access is automatically granted. But it would be silly to place a DPL0 descriptor in a CPL=3 LDT. So if you set up the descriptors rightfully even changing the RPL for higher privilege wont grant you access in less privileged segments.Cody wrote: Well, I admit you have to use RPL to do all those privilege switchings. The point I want to emphasis is that you can always manipulate these RPLs. You have full control over what RPL value to put into the selector, right? For example, you could:
mov ax, sel
and ax, 0xFFFC ; to mask RPL as 0
With that said, I am more eager to know in what cases your manipulation of RPL will be futile. Currently, if you find the RPL in your selector prevents you from doing a successful switching you can always overwrite it. I am wondering when some enforcement will be carried out that renders RPL truly unshakable.
Re:Question on RPL
Hi, Ryu
Thanks again for your help!
the procedure through it though I couldn't control where in that destination code segment I could call to (the offset is hardcoded in the descriptor). Intel stipulates that the following rules must be followed:
1) CPL <= call gate's DPL
2) RPL <= Call gate's DPL
3) Destination code segmet's DPL <= CPL
well, 1) and 3) are automatically satisfied. As to 2) I can change the selector's RPL so it will not violate the rule. So suppose someone passes me a selector which points to the Call gate's descriptor in GDT with RPL=3 in the intention to prevent me from doing a successful calling, I can always check it myself and change the selector's RPL to 2 or less. There is nothing to prevent me from changing the RPL, right?
As to the example you gave, I am not really sure if I understand it well. It appears to me that loading the segment register shouldn't cause a GPF in your case. The only violation is if both RPL and CPL > DPL. And I have no idea why Bochs would treat this to be a violation (CPL=3, RPL = 0, DPL = 3). Can you extend on that a little bit?
Thanks again for your kind help! ;D
Best regards,
Cody
Thanks again for your help!
Well, let me give another example if you are interested. Suppose a Ring3 procedure now wants to call into some Ring0 code segment's procedure via a Call Gate. I couldn't call into the destination code segment directly however, since its DPL=0 and my CPL=2. The call gate's DPL=2 so I can call intoIf that selector descriptor is DPL=3, and you set the selector's RPL=0 running in CPL=3, and also this selector is in the GDT, loading this in any segment registers will generate a GPF, Bochs will output (RPL & CPL must be <= DPL). If in the same circumstance but the selector is within LDT, from what I tested, theres no checks made and access is automatically granted. But it would be silly to place a DPL0 descriptor in a CPL=3 LDT. So if you set up the descriptors rightfully even changing the RPL for higher privilege wont grant you access in less privileged segments.
the procedure through it though I couldn't control where in that destination code segment I could call to (the offset is hardcoded in the descriptor). Intel stipulates that the following rules must be followed:
1) CPL <= call gate's DPL
2) RPL <= Call gate's DPL
3) Destination code segmet's DPL <= CPL
well, 1) and 3) are automatically satisfied. As to 2) I can change the selector's RPL so it will not violate the rule. So suppose someone passes me a selector which points to the Call gate's descriptor in GDT with RPL=3 in the intention to prevent me from doing a successful calling, I can always check it myself and change the selector's RPL to 2 or less. There is nothing to prevent me from changing the RPL, right?
As to the example you gave, I am not really sure if I understand it well. It appears to me that loading the segment register shouldn't cause a GPF in your case. The only violation is if both RPL and CPL > DPL. And I have no idea why Bochs would treat this to be a violation (CPL=3, RPL = 0, DPL = 3). Can you extend on that a little bit?
Thanks again for your kind help! ;D
Best regards,
Cody
Re:Question on RPL
In Ryu's example, CPL=3, RPL=0, and DPL=0 (not 3 as you said) so attempting to access the descriptor would result in a GPF.
I imagine RPL has something to do with the debugging intentions of protected mode. You may want to limit yourself to using a descriptor of DPL such that RPL<=DPL & CPL<=DPL. Imagine you're running some code at CPL=1 and you don't want to access ring 0 or 1 descriptors. Already you're limited to DPL>=1 but to exclude ring 1 descriptors RPL needs to be 2. I can't fathom a concrete, real-world example but you would get an exception which could be useful for debugging.
Other than that I can imagine that the combined bit width of TI and RPL being 3 is not coincidental when considering the size of a descriptor is 8 bytes. All the CPU would have to do to compute the base address of the descriptor is mask off the three lowest bits of the selector+TI+RPL and add it to the base address of the selected descriptor table. It can also determine if the descriptor extends past the table fairly easily using the masked selector value and the length of the table.
I imagine RPL has something to do with the debugging intentions of protected mode. You may want to limit yourself to using a descriptor of DPL such that RPL<=DPL & CPL<=DPL. Imagine you're running some code at CPL=1 and you don't want to access ring 0 or 1 descriptors. Already you're limited to DPL>=1 but to exclude ring 1 descriptors RPL needs to be 2. I can't fathom a concrete, real-world example but you would get an exception which could be useful for debugging.
Other than that I can imagine that the combined bit width of TI and RPL being 3 is not coincidental when considering the size of a descriptor is 8 bytes. All the CPU would have to do to compute the base address of the descriptor is mask off the three lowest bits of the selector+TI+RPL and add it to the base address of the selected descriptor table. It can also determine if the descriptor extends past the table fairly easily using the masked selector value and the length of the table.
Re:Question on RPL
At least how I take it, RPL is there so the protected mode facilities to have differnt descriptor types that will handle the protection differntly. Conforming/non-conforming is one, and possibily an opening to future descriptor types.
Re:Question on RPL
Yes, my problem too, is I cannot find a concrete example to support my idea. Well, just a few days ago, I read about a comment on Intel I386 Arch, and it's the author's opinion that I386 has many intricate designs which many of the modern OS don't utilize. The reason is either it is not efficient (like the soft task switching) or that it is too complicated or couldn't find a way to use them.blip wrote: I imagine RPL has something to do with the debugging intentions of protected mode. You may want to limit yourself to using a descriptor of DPL such that RPL<=DPL & CPL<=DPL. Imagine you're running some code at CPL=1 and you don't want to access ring 0 or 1 descriptors. Already you're limited to DPL>=1 but to exclude ring 1 descriptors RPL needs to be 2. I can't fathom a concrete, real-world example but you would get an exception which could be useful for debugging.
Other than that I can imagine that the combined bit width of TI and RPL being 3 is not coincidental when considering the size of a descriptor is 8 bytes. All the CPU would have to do to compute the base address of the descriptor is mask off the three lowest bits of the selector+TI+RPL and add it to the base address of the selected descriptor table. It can also determine if the descriptor extends past the table fairly easily using the masked selector value and the length of the table.
Anyway, I guess I would explore in the code a little bit more myself. And if I can find something noticable, I will be happy to share with you guys.
Thanks for your kind help!
Best regards,
Cody