Protecting Pages
Protecting Pages
I am almost done with my Physical Memory Manager but there is one point that still confuses me and I have not yet been able to come up with a solution to it. Suppose I am using the MEGABYTE(16) to MEGABYTE(24) as a free space for my kernel's physical memory allocation requests. MEGABYTE(0) to MEGABYTE(16) is being used by kernel.
Now PTEs 0 to 2047 are being used for kernel for allowing MEGABYTE(0) to MEGABYTE(16) being used by the kernel. Suppose I have allocated 1 page (PTE) with my Physical Memory Allocator. Due to the fact that at first all the PTEs in the range of MEGABYTE(16) to MEGABYTE(24) are empty, my PMM will allocate the first PTE which is the the PTE #2048. Now I allocate another page and my PMM will allocate PTE #2049.
I have made my allocator return the physical address of the memory that is allocated so for the first allocation it will return 0x01000000 (MEGABYTE(16)) and for the second allocation it will return 0x01001000 (MEGABYTE(16) + KILOBYTE(4)). But the problem is if I cross the 4096 boundary of the first allocated PTE, I will be using the second PTE which is also allocated so I wouldn't get a Page Fault Exception because the PTEs that have been individually allocated are contiguous so basically, I will be able to address them both.
Does anybody know how I must prevent this from happening. Should I used PTEs that are not contiguous or etc? Thank you guys in advance.
Now PTEs 0 to 2047 are being used for kernel for allowing MEGABYTE(0) to MEGABYTE(16) being used by the kernel. Suppose I have allocated 1 page (PTE) with my Physical Memory Allocator. Due to the fact that at first all the PTEs in the range of MEGABYTE(16) to MEGABYTE(24) are empty, my PMM will allocate the first PTE which is the the PTE #2048. Now I allocate another page and my PMM will allocate PTE #2049.
I have made my allocator return the physical address of the memory that is allocated so for the first allocation it will return 0x01000000 (MEGABYTE(16)) and for the second allocation it will return 0x01001000 (MEGABYTE(16) + KILOBYTE(4)). But the problem is if I cross the 4096 boundary of the first allocated PTE, I will be using the second PTE which is also allocated so I wouldn't get a Page Fault Exception because the PTEs that have been individually allocated are contiguous so basically, I will be able to address them both.
Does anybody know how I must prevent this from happening. Should I used PTEs that are not contiguous or etc? Thank you guys in advance.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Hi,
Really, it is down to the kernel to control its own memory space - in other words, you should make sure that an array at 0x1000000, for example, does not overflow to 0x1001000.
In user space, it is down to the user application to do the same thing. Because you will have set the user/supervisor PTE bit for user applications and not for the kernel, a badly written user app cannot interfere with kernel data.
If you are asking how to do this with everything in a single flat memory space, there is no way to stop apps interfering with each others code/data. You need to have a separate memory space (Page diectory) for each user app.
Cheers,
Adam
Really, it is down to the kernel to control its own memory space - in other words, you should make sure that an array at 0x1000000, for example, does not overflow to 0x1001000.
In user space, it is down to the user application to do the same thing. Because you will have set the user/supervisor PTE bit for user applications and not for the kernel, a badly written user app cannot interfere with kernel data.
If you are asking how to do this with everything in a single flat memory space, there is no way to stop apps interfering with each others code/data. You need to have a separate memory space (Page diectory) for each user app.
Cheers,
Adam
Short answer - no
The kernel can access *any* memory mapped in to its page directory - after all, it is the system supervisor and accessing another processes memory is actually useful quite a lot of the time.
As for user processes running with privilege level 3, they can only access user pages, therefore your kernel *is* protected from erroneous user processes.
A user process can access *any* user page mapped in to its page directory. This is why we load CR3 with a different page directory for each user process - you only map a user page in to a page directory beloinging to the intended process. The memory that a single process sees is its 'process space'.
If you map a user page in to 2 page directories, that page is shared and can be used for communication between the 2 (or more) processes. This obviously needs careful monitoring.
So the answer is: The kernel is automatically protected (you will get a PFE if you access a supervisor page from user mode), but user memory needs to be protected by switching CR3.
HTH
Adam
The kernel can access *any* memory mapped in to its page directory - after all, it is the system supervisor and accessing another processes memory is actually useful quite a lot of the time.
As for user processes running with privilege level 3, they can only access user pages, therefore your kernel *is* protected from erroneous user processes.
A user process can access *any* user page mapped in to its page directory. This is why we load CR3 with a different page directory for each user process - you only map a user page in to a page directory beloinging to the intended process. The memory that a single process sees is its 'process space'.
If you map a user page in to 2 page directories, that page is shared and can be used for communication between the 2 (or more) processes. This obviously needs careful monitoring.
So the answer is: The kernel is automatically protected (you will get a PFE if you access a supervisor page from user mode), but user memory needs to be protected by switching CR3.
HTH
Adam
- mathematician
- Member
- Posts: 437
- Joined: Fri Dec 15, 2006 5:26 pm
- Location: Church Stretton Uk
You can prevent apps from interfering with one another by clearing the present bit for all pages (or page tables) except those belonging to the OS and currently executing app. The OS would then need to maintain another flag to keep track of what is really in memory and what is not. (Suggestion comes from the Intel manual.)
I must admit that I felt suitably appalled to hear that Intel were dropping segmentation without (apparently) putting any alternative protection mechanism in place.
I must admit that I felt suitably appalled to hear that Intel were dropping segmentation without (apparently) putting any alternative protection mechanism in place.
Only "useful" if you are using a single address space for all processes.mathematician wrote:You can prevent apps from interfering with one another by clearing the present bit for all pages (or page tables) except those belonging to the OS and currently executing app. The OS would then need to maintain another flag to keep track of what is really in memory and what is not. (Suggestion comes from the Intel manual.)
The default way to protect is to use the protection "Rings", which as already been touched upon in this thread.
You must be talking about EM64T... well... go ahead and look at the manual... paging protects just fine. Moreover, in long mode paging even protects pages against Ring-0 write-access if indicated. This could be useful for monolithic drivers.mathematician wrote: I must admit that I felt suitably appalled to hear that Intel were dropping segmentation without (apparently) putting any alternative protection mechanism in place.
As for completely dropping segmentation, that is a negative as FS/GS segment overrides are still honored in long mode.
- mathematician
- Member
- Posts: 437
- Joined: Fri Dec 15, 2006 5:26 pm
- Location: Church Stretton Uk
It won't protect applications from one another (all running in ring 3, and with an address space spanning the full 4Gb. Even in 32 bit mode the segment registers have been effectively knackered if you have any thoughts about porting to 64 bit mode in the future).SpooK wrote:[
Only "useful" if you are using a single address space for all processes.
The default way to protect is to use the protection "Rings", which as already been touched upon in this thread.
If it has been dropped for the code segment and the default data segment, for all practical purposes it has been dropped. You certainly can't use segmentation as a protection mechanism nowadays.As for completely dropping segmentation, that is a negative as FS/GS segment overrides are still honored in long mode.
Last edited by mathematician on Thu Jun 07, 2007 9:29 am, edited 1 time in total.
I think people are talking at cross-purposes. It will protect ring 3 apps from one another if you are using separate page directories, but not if you are using one PD for all tasks.It won't protect applications from one another (all running in ring 3, and with an address space spanning the full 4Gb with the segment registers knackered).
actually, segmentation wont protect ring3 applications from each other, as it is a relatively simple matter to change your DS to another applications segment descriptor -- the solution for this, is to either unmap the segment descriptors (by clearing the present bit), or by rewriting a single descriptor for each application, -- which makes segmentation protections exactly the same as paging, to truly protect ring3 tasks from each other, you must modify the address translation between tasks (in paging, by using a separate (or modified) PD/PDPT, or in segmentation, by using a separate (or modified) GDT)
For accuracy's sake I think we need to add in 'by using a separate LDT', but then I really don't recommend that. Use paging.JAAman wrote:to truly protect ring3 tasks from each other, you must modify the address translation between tasks (in paging, by using a separate (or modified) PD/PDPT, or in segmentation, by using a separate (or modified) GDT)
Regards,
John.