Hey all,
I was browsing wikipedia and stumbled upon this interesting thing about a special type of memory protection. It uses, from what I can tell, a chunk of memory is given a unique identification key to be used in conjunction with an application's assigned key. I'm guessing applications are given a key based on which blocks are free (probably size as well) which restricts the blocks of memory it can access.
So here's my question: how feasible would it be to implement "key protection", as I like to call it, in software? I would assume that under the x86, one could use the debug registers to restrict access, but there's a problem with that. The debug registers can either fire a breakpoint on the access of one, two, or four bytes only. No more. Damn.
So how else would it be done? How portable would it be? Is it worth to use instead of segmentation or (ye-eech) paging? Would it be anything else than just a "cool idea"?
I'd love to hear your thoughts on this.
Cheers,
--Troy
"Key"-based memory protection
- Troy Martin
- Member
- Posts: 1686
- Joined: Fri Apr 18, 2008 4:40 pm
- Location: Langley, Vancouver, BC, Canada
- Contact:
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: "Key"-based memory protection
It seems like just another way to implement paging (protection wise, not flexibility wise), except with one master table for all physical memory instead of separate tables for virtual address spaces. Why wouldn't you use paging, which has hardware acceleration (probably thousands of times faster than breakpoint interrupting on *every memory access*) and gives a great virtual address space abstraction that removes the need for any relocation? You would really need hardware support to make it practical. Nobody implements a MMU in software for a reason.
Paging is not that hard, if that's what you're trying to avoid - I've got my entire memory manager in about 150 lines of C. The trick is using recursive mapping for everything and avoiding the kernel heap entirely.
Paging is not that hard, if that's what you're trying to avoid - I've got my entire memory manager in about 150 lines of C. The trick is using recursive mapping for everything and avoiding the kernel heap entirely.
Re: "Key"-based memory protection
You can't unless you have managed code. And that goes for all types of memory protection: if it is not supported in hardware, you cannot enforce it by using software(1).Troy Martin wrote:So here's my question: how feasible would it be to implement "key protection", as I like to call it, in software?
(1) Tricks like using debug registers or the like I also call "supported by hardware", although it is a bit of a grey area, as it is not hardware support for memory protection per se.
JAL
Re: "Key"-based memory protection
Hi,NickJohnson wrote: The trick is using recursive mapping for everything and avoiding the kernel heap entirely.
What is recursive mapping, would you mind give more details on that?
Cheers
torshie
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: "Key"-based memory protection
The idea is to leverage the two-tiered page directory/table setup and the fact that a page directory is also a valid page table. Normally, you would have a page directory with a bunch of page tables in it. With recursive mapping, one of the page table positions points to the current page directory, so that the page directory is used both as a page directory *and* a page table that maps all of the currently used tables into a 4MB chunk of virtual memory.torshie wrote:Hi,NickJohnson wrote: The trick is using recursive mapping for everything and avoiding the kernel heap entirely.
What is recursive mapping, would you mind give more details on that?
Cheers
torshie
Here's an example. Let's say you have a page directory at physical address 0x1000, and you also have a page table at physical address 0x2000 that has some mappings in it at the second-to-last position in the page directory. You map the page directory recursively in the last position within itself. The page directory would look like this (in nasm syntax):
Code: Select all
times 1022 dd 0x00000000
dd 0x00002003
dd 0x00001003
This allows you to quickly find the contents of page tables, because they are in fixed positions and are addressed continguously, and appear when the page directory changes. It also means you don't have to keep track of anything but the physical address of the page direcotory, or even keep anything extra in the address space, and still perform all paging actions. That eliminates a lot of address space usage and the need for a virtual memory allocator entirely. You can also map other page directories in the current one, and access their tables' contents contiguously as well.
Here's a piece of my memory manager (all of the general page manipulation) that should give a good explanation as well, at least of the non-initialization part:
Code: Select all
ptbl_t *cmap = (void*) (PGE_MAP + 0x3FF000);
page_t *ctbl = (void*) PGE_MAP;
void page_touch(uint32_t page) {
page &= ~0x3FFFFF;
if (cmap[page >> 22] & PF_PRES) return;
cmap[page >> 22] = frame_new() | (PF_PRES | PF_RW | PF_USER);
pgclr(&ctbl[page >> 12]);
}
void page_set(uint32_t page, page_t value) {
page &= ~0xFFF;
if ((cmap[page >> 22] & PF_PRES) == 0) page_touch(page);
ctbl[page >> 12] = value;
asm volatile ("invlpg %0" :: "m" (page));
}
page_t page_get(uint32_t page) {
return (cmap[page >> 22] & PF_PRES) ? ctbl[page >> 12] : 0;
}