Getting address of symbol from kernel's symbol table - linux-kernel

arif#khost:~/src/linux$ global -x ip_rcv_finish
ip_rcv_finish 319 net/ipv4/ip_input.c static int ip_rcv_finish(struct sk_buff *skb)
Now if i want to use this function i need to initialize a pointer to this function.
To be able to do that i need the address of the function.
I've seen that from user space i can read /proc/kallsyms to get an address of a symbol. Is their any similar mechanism exist where i can read the symbol table to extract a symbol's address from kernel space?

Depending on your kernel version, you can use kallsyms_lookup_name and/or kallsyms_on_each_symbol to obtain the addresses of the symbols from code running in the kernel space.
This only works if CONFIG_KALLSYMS is set in the kernel configuration.
Note that I would not recommend looking up the addresses of the functions to be called though unless there is no better way (kernel API) to do what you would like to. Still, if nothing else helps, kallsyms_*() API may be the way to go.

Related

Get memory address ranges for Windows program

I'm trying to read the memory of a Windows program based on a pointer I find by using ModuleInfo to get the address starting point and size of the module. But that pointer points to memory outside that modules address space, is there a way to find out the program uses that section of memory without having to find a pointer to it first?
See if the program in question has an interface ( https://en.m.wikipedia.org/wiki/Interface_(computing) ) that can be used to interface with said program. If there is no documented interface, attempting to tamper with that programs memory is a bad idea; and will most likely result in undefined behaviour. If this does not answer your question I suggest you edit it to specify exactly which program this is about.

LLDB and the memory addresses of library functions

I have a "Hello World" program to which I've attached lldb. I'm trying to answer a few questions for myself about the results I get when I try to get the address of library functions:
(lldb) image lookup -n printf
1 match found in /usr/lib/system/libsystem_c.dylib:
Address: libsystem_c.dylib[0x000000000003f550] (libsystem_c.dylib.__TEXT.__text + 253892)
Summary: libsystem_c.dylib`printf
(lldb) image lookup -n scanf
1 match found in /usr/lib/system/libsystem_c.dylib:
Address: libsystem_c.dylib[0x000000000003fc69] (libsystem_c.dylib.__TEXT.__text + 255709)
Summary: libsystem_c.dylib`scanf
(lldb) expr &printf
(int (*)(const char *__restrict, ...)) $2 = 0x00007fff6f8c5550 (libsystem_c.dylib`printf)
(lldb) expr &scanf
error: unsupported expression with unknown type
I have three questions here:
What kind of address is 0x00007fff6f8c5550? I assume it is the function pointer to printf. Is this a virtual address that exists only in the mapped space of the current process? If yes, why does another program return the same address for printf?
Assuming it's some global shared address that is the same for every process, would modifying the contents of the data at this address (which I haven't been able to do yet) create a copy of the modified memory page and will the address change? (i'm on Mac OS and I assume one process cannot change shared memory for another process)
Why does expr &scanf not work, but expr &printf does?
What kind of address is 0x00007fff6f8c5550? I assume it is the function pointer to printf.
Yes, that's correct.
Is this a virtual address that exists only
in the mapped space of the current process?
Well, yes and no. It is a virtual address specific to your process and you should not assume it's valid in another process. But:
If yes, why does another
program return the same address for printf?
As an optimization, macOS uses a shared mapping for a lot of the system libraries. They are loaded once at boot and used by all processes. For a given boot, the address is constant across all such processes. However, the address is randomized each boot for security.
Assuming it's some global shared address that is the same for every process, would modifying the contents of the data at this address
(which I haven't been able to do yet) create a copy of the modified
memory page and will the address change?
Well, it is mapped copy-on-write. So, modifying it would create a copy. However, that wouldn't change its address. The OS would simply modify the mapping so that the memory around that address is private to your process.
(i'm on Mac OS and I assume
one process cannot change shared memory for another process)
Well, processes can cooperate to have writable shared memory. But, in general, you're correct that security precautions prevent unwanted modifications to a process's memory.
Why does expr &scanf not work, but expr &printf does?
Your program (presumably) doesn't use scanf, so there's no debugging information regarding it. The main thing lldb is missing is the type of scanf. If you use a cast expression, it can work:
(lldb) p scanf
error: 'scanf' has unknown type; cast it to its declared type to use it
(lldb) p &scanf
error: unsupported expression with unknown type
(lldb) p (int(*)(const char * __restrict, ...))scanf
(int (*)(const char *__restrict, ...)) $3 = 0x00007fffd7e958d4 (libsystem_c.dylib`scanf)
Conversely, it works for printf because your program does use it.

Working of mmap()

I am trying to get an idea on how does memory mapping take place using the system call mmap.
So far I know mmap takes arguments from the user and returns a logical address of where the file is stored. When the user tries to access it takes this address to the map table converts it to a a physical address and carries the operation as requested.
However I found articles as code example and Theoretical explanation
What it mentions is the memory mapping is carried out as:
A. Using system call mmap ()
B. file operations using (struct file *filp, struct vm_area_struct *vma)
What I am trying to figure out is:
How the arguments passed in the mmap system call are used in the struct vm_area_struct *vma) More generally how are these 2 related.
for instance: the struct vm_area_struct has arguments such as starting address, ending address permissions,etc. How are the values sent by the user used to fill values of these variables.
I am trying to write a driver so, Does the kernal fill the values for variables in the structure for us and I simply use it to call and pass values to remap_pfn_range
And a more fundamental question, why is a different file systems operation needed. The fact that mmap returns the virtual address means that it has already achieved a mapping doesnt it ?
Finally I am not that clear about how the entire process would work in user as well as kernal space. Any documentation explaining the process in details would be helpful.

How to translate a delegate to absolute address in DRAM?

I'd like to translate the delegate members .ptr and .funcptr to an absolute address that matches something in the executable image in DRAM.
The goal is not to call, neither to modify, but rather to allow the target to disassemble itself at run-time, when its own image is loaded in DRAM.
So far it already works with global functions.
Is it possible ?
The address of a delegate is the value of the .funcptr property. The type of this property is a bit misleading - it is of type function and does not list the hidden argument that is actually expected for passing the context in, but for just getting the address, you can ignore the type (explicitly casting to void* or size_t if you like to change the type) and just look at the address.
This isn't the address in physical memory, you'd have to ask the operating system for that, but since the virtual address it gives is automatically translated by the processor, it is most likely what you want anyway.

User space access from Kernel space - get_user_pages

I'd like pass a pointer from a user space memory into a function in my kernel module. I don't want to use copy_from_user. I've read that I should use get_user_pages function.
For example one page.
struct page **pages;
pages = kmalloc(1 * sizeof(*pages), GFP_KERNEL);
down_read(&current->mm->mmap_sem);
get_user_pages(current,current->mm,uaddr, 1, 1, 0,pages,NULL);
up_read(&current->mm->mmap_sem);
uaddr is an address in User Space.
After doing this, am I allowed to cast and pass uaddr into my kernel module function? Or maybe I have to use these struct pages in some way?
Why do I have to use down/up read?
After everything do I have to use SetPageDirty() and page_cache_release() functions ?
No, you cannot directly access the userspace pages via uaddr. The struct pages are filled out to allow the kernel to access the physical pages that correspond to the userspace pages. Note also that they are most unlikely to be contiguous, so one must be careful to use the correct page index into the array from the start of the uaddr.
You are changing the page mapping structures for this process, so need to protect them while the page mapping in the kernel is set up.
When you are done with the mappings that were setup by get_user_pages(), you must 'release' them by the referenced functions.
This is not what get_user_pages is for (and no - you can't then just cast and pass uaddr into your kernel module function).
If you don't want to call copy_from_user in the calling function, then just pass a void __user * to your module function and have it do the copy_from_user.
You can only use the user pages for page type activity, for example setting up Scatter/Gather DMA into userspace memory. You cannot use it to directly access user space from kernel mode code. Hence the copy_to/from functions that are there for that reason. Unless your moving large amounts of data why not use these functions?
Once you get the valid user space address, use get_user_pages to get the struct page pointer. once struct page pointer received , to access it in the kernel mode you have to map it to kernel virtual address by using kmap. hope that helps

Resources