Priviledge levels
Priviledge levels
Hello,
I would like to know how do you switch between privilege levels; for example, the kernel is running in ring 0 and the user programs are running in a lower level (ring 3). Is that done by having in the GDT two code segments and two data segments each with a different DPL and loading the kernel in the ring0 code segment and the user programs in the ring3 code segment or there's another method?
Thanks for any help.
I would like to know how do you switch between privilege levels; for example, the kernel is running in ring 0 and the user programs are running in a lower level (ring 3). Is that done by having in the GDT two code segments and two data segments each with a different DPL and loading the kernel in the ring0 code segment and the user programs in the ring3 code segment or there's another method?
Thanks for any help.
Re:Priviledge levels
You have to have those segments in the GDT but to switch between them you have to reload CS, DS etc. TO move UP a level (i.e. ring3 -> ring0) you have to use an interrupt. So:-
ring3 -> interrupt enrty -> interrupt modifies stack -> interrupt exit (pops different CS) -> ring0
To move down a priviledge level you can just setup a stack with the required info and do "IRET" but it is a lot easier to do it in the same way as above. Some good example code of this (and a simple TSS for seperate kernel and user stacks) is here
Pete
ring3 -> interrupt enrty -> interrupt modifies stack -> interrupt exit (pops different CS) -> ring0
To move down a priviledge level you can just setup a stack with the required info and do "IRET" but it is a lot easier to do it in the same way as above. Some good example code of this (and a simple TSS for seperate kernel and user stacks) is here
Pete
Re:Priviledge levels
Ive wondered about this. Whats the differens between different privilege levels? Suppose I run an application. I dont want my application to be able to overwrite something important or anything like that. But I do want my program to be able to change variables (of course). How do I do this? I have already prevented the applications from overwriting (by paging and only map the memory the program has), but what do I use the privilege levels for?
Re:Priviledge levels
Only Ring 0 code may reload the GDT, IDT etc. for example.
Such tasks are then to be priviliged!
Such tasks are then to be priviliged!
Re:Priviledge levels
The tradition is to have two priviledge levels - kernel space and user space.
Applications run in user space. All the dangerous things are forbidden since the app runs in ring 3. To get things done, they call API functions, which in turn call kernel functions. They are called by placing parameters somewhere specific (e.g. registers), then calling something that invokes the kernel (e.g. interrupt handler in ring 0).
The kernel wakes up ("huh? who's dere? Some app called me..."), the interrupt handler gathers the parameters (e.g. from the registers), executes what the kernel function does, and returns from the interrupt (we're back in the application's user space).
Only the kernel (ring 0) is allowed to do the potentially disastrous things - writing to certain memory areas (I/O, control registers), fiddling with the CPU (task switching, paging, etc.) and other things. Hence, it is in a position where it can check whether the application in question is allowed to do what it requested.
HTH.
Applications run in user space. All the dangerous things are forbidden since the app runs in ring 3. To get things done, they call API functions, which in turn call kernel functions. They are called by placing parameters somewhere specific (e.g. registers), then calling something that invokes the kernel (e.g. interrupt handler in ring 0).
The kernel wakes up ("huh? who's dere? Some app called me..."), the interrupt handler gathers the parameters (e.g. from the registers), executes what the kernel function does, and returns from the interrupt (we're back in the application's user space).
Only the kernel (ring 0) is allowed to do the potentially disastrous things - writing to certain memory areas (I/O, control registers), fiddling with the CPU (task switching, paging, etc.) and other things. Hence, it is in a position where it can check whether the application in question is allowed to do what it requested.
HTH.
Every good solution is obvious once you've found it.
Re:Priviledge levels
Solar: But do I have to create a complete new segment for the running applications/the kernel? Always had in mind that u should never bother about segments when using paging..
Re:Priviledge levels
You'll need at least 4 segments unless you want everything running in Ring 0.
One Code/Data pair for Ring 0 for trusted (System) code/data
One Code/Data pair for untrusted (User) code/data (Anything but Ring 0)
That gives you enough separation between userspace and kernelspace to get by with.
Running everything at Ring 0 is problematic, and should probably be avoided IMHO. If you were to try you'd have to either only run trusted applications or perform some sort of scanning for privileged instructions.
Remember that just because the x86 architecture supports multiple privilege levels does not mean that you MUST use them.
The 4 levels are usually not much use unless you are using a segmented memory model, or a segmented/paged mix. Most modern operating systems (AFAIK) just use 2 of the privilege levels, a flat memory model, and pretty much ignore everything about segmentation after that aside from certain special cases (Eg Certain Linux drivers *cough*Nvidia*cough*).
One Code/Data pair for Ring 0 for trusted (System) code/data
One Code/Data pair for untrusted (User) code/data (Anything but Ring 0)
That gives you enough separation between userspace and kernelspace to get by with.
Running everything at Ring 0 is problematic, and should probably be avoided IMHO. If you were to try you'd have to either only run trusted applications or perform some sort of scanning for privileged instructions.
Remember that just because the x86 architecture supports multiple privilege levels does not mean that you MUST use them.
The 4 levels are usually not much use unless you are using a segmented memory model, or a segmented/paged mix. Most modern operating systems (AFAIK) just use 2 of the privilege levels, a flat memory model, and pretty much ignore everything about segmentation after that aside from certain special cases (Eg Certain Linux drivers *cough*Nvidia*cough*).
Re:Priviledge levels
Alright
But, suppose I switch to an application. The kernel runs on ring 0, then I load the application, setting the new segments into the registers(ring 3 segments), and then I launch the application. But how do I switch back to the ring 0 segment when I want my kernel to do something? Cause you should not be able to switch to more priveleged levels, but you have to cause you need to switch back to the kernel huh?
But, suppose I switch to an application. The kernel runs on ring 0, then I load the application, setting the new segments into the registers(ring 3 segments), and then I launch the application. But how do I switch back to the ring 0 segment when I want my kernel to do something? Cause you should not be able to switch to more priveleged levels, but you have to cause you need to switch back to the kernel huh?
Re:Priviledge levels
I mean they said you should use interrupts.. but can interrupts do this? I mean, why can an ISR change the segments if a normal program cant? Can I make just a bit of the memory be ring 0 and the rest 3 (at the same time)?
Re:Priviledge levels
Most of the time, you want your user segments in ring 3, not just "anything but ring 0". Though many instructions are only allowed if running in ring 0, there are some that are only not allowed when running in ring 3. If you really dont care about those being run by user-processes then thats fine but for the most part ring 3 is the best way to goCurufir wrote: You'll need at least 4 segments unless you want everything running in Ring 0.
One Code/Data pair for Ring 0 for trusted (System) code/data
One Code/Data pair for untrusted (User) code/data (Anything but Ring 0)
yes, they can. When you create an interrupt descriptor, you specify both the DPL (where its allowed to be called from) and the code-segment that the handler is in. This way you can make a soft-interrupt (e.g. int 0x40 or something) have a DPL of three, but run a handler in your ring0 code segment, and in the process of calling the interrupt handler there is a switch to ring 0. At the same time, you can make the hardware interrupts and exceptions have a DPL of 0, so a user program can't just say int 0x20 and call your timer handler (assuming int 0 mapped to int 0x20 like most people do)I mean they said you should use interrupts.. but can interrupts do this?
The reason this is allowed when going direct from user-land is not, is that only ring 0 code can set up this interrupt descriptor in the first place, so you still have complete control over switching from rin3 into ring0
Re:Priviledge levels
But what happends if I set the DPL of an exception to 0? What will then happend when I get an exception in a program running in ring 3? The ISR cannot be reached?
Re:Priviledge levels
Cause I want to prevent a user from reaching the handler by software, typing INT 0 (Divide by zero), but if the Exception occurs in his/her program, of course I want to run the handler.