Re: Verify Kernel Pointer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




I delved a little in my "Understanding the Linux Kernel". It's the first
edition, but I guess it's a starting point. Here's what I found ...



mem_map is an array of page structure, each element of this array is
of "page" structure type. Actually mem_map is used for reverse
mappeing of physical memory of system. This array represents the
physical memory interms of page sturcture. Lets say for simplicity we
have total physical memory of 256K and one one physical page of 4K,
then in taht case mem_map will have 256/4 = 64 enteries and max_mapnr
will be set to 64.


Linux keeps track of each frame in the system. Each frame has a structure
keeping some info about it. The table of all these structure is the mem_map. (as you said.)

So as per the kernel sources (file: include/asm-i386/page.h)
#define pfn_valid(pfn)          ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr)  pfn_valid(__pa(kaddr) >> PAGE_SHIFT)

virt_addr_valid() macro only tells whether the given virtual address
can be mapped to any physical page or not. __pa() macro gives the
physical address for a given virtual address just by subracting the
PAGE_OFFSET from given virtual address. Now then we right shift that
physical address by page size which gives us the page number in which
our physical adress falls and then we look if this page number is less
than the total number of physical pages in system, if yes then it
means we can mapped this virtual address to some physical address else
our given virtual address can not be mapped to any physical address
in system.

I think I get it. You don't have more pages than RAM frames (can't the
kernel swap its own pages?) so all this check does is make sure the
address falls in a page you are allowed to use.

My statement here is not correct.
You can have (much) more pages than frames.
I am not sure whether Linux swaps kernel pages, but some pages can be swapped out theoretically speaking.

As kernel occupies contiguous physical memory, virt_addr_valid() only
tells if this virtual address can be mapped to some physical location
in RAM or is it going outside that (means system dont have that much
RAM so that it can map this large virtual address). Lets say we have
pass vitual address 0xC0080000 (PAGE_OFFSET + 512 K) and we only have
physical RAM of 256K (just for keeping the example simple). in this
case total number of physical pages will be 256 / 4 = 64 (each page
being 4K) and the page frame number we will get for our page will be
((virtual address - PAGE_OFFSET) >> 12) = 128. This means our virtual
address will be there in 128th page frame, but 128th page frame does
not exist in our RAM, so its not a valid or rather not at all possible
mappable virtual address. Hope with this example it clears that
virt_addr_valid() function only tells you if virtual address can be
mapped to some physical page or not and nothing more than that.

AFAIK, kernel memory is never swapped out.

What bothered be was the macro __pa() that translates virtual to physical addresses by simple substruction. This would imply that virtual addresses are contiguous in RAM, external fragmentation, and other ouchies.

I read some and eventually saw that:
The kernel has 1G of virtual addresses (usually). The lower part of this
1G is used to map the physical memory. The upper part of it is used for virtual addresses.
So we have this mem-map:

[ map of ram  |     8MB     |   more kernel memory    ]
^             ^             ^                         ^
PAGE_OFFSET   high_memory   VMALLOC_START             4G

Where PAGE_OFFSET is 0xC0000000.

high_memory is a variable that tells where the mapping of physical RAM ends.

VMALLOC_START points to where starts the area that is allocated virtually.

So, addresses between PAGE_OFFSET and high_memory can be translated with __pa(), others cannot.



So if we go back to Talib's original question, the only thing he can do is
traverse the page table tree to see if the address is indeed valid.
I think this is what virt_to_page(addr) does.

I dont think he need to traverse the page tables as he has to verify
the kernel virtual address not the user virtual address. He can
definitely use virt_addr_valid() to make sure that the passed virtual
address is atleast mappable to some physical address in RAM and then
over that use his signature and pid matching mechanisum to make sure
that its the same memory location whose pointer he passed back to user
earlier.

I am not sure how Talib allocated his structures. If it's with kmalloc the __pa() and virt_to_page() can work for him. And I guess these addresses are always valid as they map the RAM (which is always there hopefully).

If its with vmalloc then he probably needs to traverse the page-table structure.

Having understood all this, and applying this information to the
actual problem of verifying the virtual address, we can use this macro
to just make sure that the kernel virtual address passed by user space
back to kernel falls in kernel virtual address space but, we can not
be sure if the given address is the same as we passed it to user space
earlier, for that as mentioned by some one we need to user some
ginature in the structure being pointed by this virtual address.

You have to check first that the virtual address is mapped to real a
frame, or you'll get a kernel panic. no?


What I still don't understand is how is this mapping happens on machines where the kernel space is of size 1G and they have more than 1G of RAM.

Probably only a small portion of the RAM is mapped.

Does what I wrote make sense, or am I so tied up with my own un-understanding that I can't even notice it?


Hayim.

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux