Are 32 bit pointers valid in 64 bit process? - 64-bit

Here is my issue. I implemented a Win 7 x64 process talking to a x32 process by following this link
The x64 process retrieves fine a x32 pointer (p_x32 below) to myClass:
myClass * POINTER_32 p = (myClass * POINTER_32)p_x32;
The trouble is that calling a method on 'p' crashes with memory violation. Indeed, under VS debugger I can see that 'p' members are not in order, i.e. the values are bogus. Digging further I found this link
Where the author says: "A handle or pointer cannot be serialized, it is only valid in the process that created it". As said above, apparently the pointer can be serialized (I used INT_PTR) but I wonder if "it is only valid in the process that created it" part is correct.
Thanks in advance.

The documentation is correct - the pointer is only valid in the originating process because the pointers are interpreted relative to the process's memory space. Therefore you cannot pass a pointer between processes and dereference it. You must serialize (deep copy) the actual data and transfer it to the other process.
The exception is you can setup specific "shared memory" spaces between the processes on Windows. Even then though the pointer values themselves are not guaranteed to be identical.

Each process has it's own virtual memory address space. If you pass pointers across process boundaries, they have a completely different meaning in the target process.

Related

Access "current_task" pointer of another cpu in a SMP based linux system

I'm writing some kernel driver where I need to check which thread is running at a certain point on another cores. My driver runs one kernel thread on per core and I need to sync from time to time some of the threads to do certain task. What I can observe from debugging logs is that sometimes one thread waits for some other threads too much. I did some patch where I store the __preempt_count on other cores to check if any softirq/hardirq or preemption disabled delays my thread.
I also used the FTRACE to check the irqsoff and preemptirqsoff for the max duration of IRQs off and preemption disabled.
Till now I was able to spot kerneloops thread which is disabling interrupts up to 20msec, which I find too long.
Did a systemctl disable kerneloops and got rid of this issue.
Now I seem to deal with some preemption disabled windows. For future analysis of this driver I need a way to figure out which threads are being executed at a particular point in time on other cores. I'm trying to use FTRACE mainly with events for IRQ entry/exit, I also use trace_printk to push some debug log in the ftrace buffer to to have everything in one log, etc.
However, one thing that I would like to do is to access the current_task structure of other cores (the current ptr) and print the comm field which gives the name of the task (or pid value).
But I'm having hard times in getting this done.
For __preempt_count I had no issue:
int *p = per_cpu_ptr(&__preempt_count,cpu);
pr_info("Preempt count of cpu%u is 0x%08x\n",cpu,*p);
So far I had no issue with declaring or accessing per cpu variables, but for some reason, the current_task pointer triggers a page fault when trying to access it.
char buf[10];
struct task_struct *task = per_cpu_ptr(current_task,cpu);
snprintf(buf,8,"%s",task->comm);
pr_info("Task name: %s",buf);
Above code triggers always a page fault, NULL ptr bla bla.
I couldn't find the reason till now. I tried to print the pointer value for task, I got the same page fault.
Might be this because the address is not accessible by other cores? In kernel space should not be the case afaik. I also had no issue till now with per core variables and I played a lot with this.
Bottom line: what would be the right approach to access the current_task of other cores and print the comm/pid fields?
Many Thanks,
Daniel
I finally figured out what was wrong.
The difference between __preempt_count and current_task is that first one is defined as an int variable, whereas the 2nd one as a pointer to structure. In other words 1st one is defined as a variable and the 2nd one as a pointer.
Now, looking deeper into per cpu variables, they are just variables allocated by the compiler in separate memory locations, like an array. When per_cpu_ptr for a variable Foo is called, then the macro computes something like Foo[cpu], but that means the per_cpu_ptr needs the actual base address of the variable, meaning the & so that it can compute the relative address value starting from this.
When declaring: foo = per_cpu_ptr(&__preempt_count,cpu) , this address is already given = &__preempt_count
When declaring: bar = per_cpu_ptr(current_task,cpu), this address is not given, as the & is missing here. The current_task is a pointer but not the base address of the current_task array.
In both above cases the argument to per_cpu_ptr is a pointer, but here my understanding was wrong, it was not clear to me what is actually the pointer of the variable I need to pass, now it's clear: I have to pass the base address of the variable(var or pointer doesn't matter) so that the macro can compute the relative address for that cpu.
Therefore the right approaches that work are:
bar = per_cpu(current_task,cpu) which translates into *per_cpu_var(&current_task,cpu)
or directly
bar = *per_cpu_var(&current_task,cpu);

what is The poisoned NUL byte, in 1998 and 2014 editions?

I have to make a 10 minutes presentation about "poisoned null-byte (glibc)".
I searched a lot about it but I found nothing, I need help please because operating system linux and the memory and process management isn't my thing.
here is the original article, and here is an old article about the same problem but another version.
what I want is a short and simple explanation to the old and new versions of the problem or/and sufficient references where I can better read about this security threat.
To even begin to understand how this attack works, you will need at least a basic understanding of how a CPU works, how memory works, what the "heap" and "stack" of a process are, what pointers are, what libc is, what linked lists are, how function calls are implemented at the machine level (including calls to function pointers), what the malloc and free functions from the C library do, and so on. Hopefully you at least have some basic knowledge of C programming? (If not, you will probably not be able to complete this assignment in time.)
If you have a couple "gaps" in your knowledge of the basic topics mentioned above, hit the books and fill them in as quickly as you can. Talk to others if you need to, to make sure you understand them. Then read the following very carefully. This will not explain everything in the article you linked to, but will give you a good start. OK, ready? Let's start...
C strings are "null-terminated". That means the end of a string is marked by a zero byte. So for example, the string "abc" is represented in memory as (hex): 0x61 0x62 0x63 0x00. Notice, that 3-character string actually takes 4 bytes, due to the terminating null.
Now if you do something like this:
char *buffer = malloc(3); // not checking for error, this is just an example
strcpy(buffer, "abc");
...then that terminating null (zero byte) will go past the end of the buffer and overwrite something. We allocated a 3-byte buffer, but copied 4 bytes into it. So whatever was stored in the byte right after the end of the buffer will be replaced by a zero byte.
That was what happened in __gconv_translit_find. They had a buffer, which had been allocated with enough space to append ".so", including the terminating null byte, onto the end of a string. But they copied ".so" in starting from the wrong position. They started the copy operation one byte too far to the "right", so the terminating null byte went past the end of the buffer and overwrote something.
Now, when you call malloc to get back a dynamically allocated buffer, most implementations of malloc actually store some housekeeping data right before the buffer. For example, they might store the size of the buffer. Later, when you pass that buffer to free to release the memory, so it can be reused for something else, it will find that "hidden" data right before the beginning of the buffer, and will know how many bytes of memory you are actually freeing. malloc may also "hide" other housekeeping data in the same location. (In the 2014 article you referred to, the implementation of malloc used also stored some "flag" bits there.)
The attack described in the article passed carefully crafted arguments to a command-line program, designed to trigger the buffer overflow error in __gconv_translit_find, in such a way that the terminating null byte would wipe out the "flag" bits stored by malloc -- not the flag bits for the buffer which overflowed, but those for another buffer which was allocated right after the one which overflowed. (Since malloc stores that extra housekeeping data before the beginning of an allocated buffer, and we are overrunning the previous buffer. You follow?)
The article shows a diagram, where 0x00000201 is stored right after the buffer which overflows. The overflowing null byte wipes out the bottom 1 and changes that into 0x00000200. That might not make sense at first, until you remember that x86 CPUs are little-endian -- if you don't understand what "little-endian" and "big-endian" CPUs are, look it up.
Later, the buffer whose flag bit was wiped out is passed to free. As it turns out, wiping out that one flag bit "confuses" free and makes it, in turn, also overwrite some other memory. (You will have to understand the implementation of malloc and free which are used by GNU libc, in order to understand why this is so.)
By carefully choosing the input arguments to the original program, you can set things up so that the memory overwritten by the "confused" free is that used for something called tls_dtor_list. This is a linked list maintained by GNU libc, which holds pointers to certain functions which it must call when the main program is exiting.
So tls_dtor_list is overwritten. The attacker has set things up just right, so that the function pointers in the overwritten tls_dtor_list will point to some code which they want to run. When the main program is exiting, some code in libc iterates over that list and calls each of the function pointers. Result: the attacker's code is executed!
Now, in this case, the attacker already has access to the target system. If all they can do is run some code with the privilege level of their own account, that doesn't get them anywhere. They want to run code with root (administrator) privileges. How is that possible? It is possible because the buggy program is a setuid program, owned by root. If you don't know what "setuid" programs in Unix are, look it up and make sure you understand it, because that is also a key to the whole exploit.
This is all about the 2014 article -- I didn't look at the one from 1998. Good luck!

Kernel Panic -- Failed copy_from_user, kmalloc?

I am writing a rootkit for my OS class (the teacher is okay with me asking for help here). My rootkit hooks the sys_read system call to hide "magic" ports from the user. When I copy the user buffer *buf (one of the arguments of sys_read) to kernel space (into a buffer called kbuf) I get kernel panic/core dump error. It is possible that this is just because breaking read brings the system to a halt, but I wonder if anyone has any perspective on this.
The code is available online. Look at line 207: https://github.com/joshimhoff/toykit/blob/master/toykit.c
I hooked getdents and used copy_from_user to bring the getdents structs into kernel space, and this worked well! I am not sure what is different about read.
Thanks for the help!
I figured it out. I called the actual sys_read function and didn't check the return value. Sometimes it is negative to indicate an error. Instead of failing early, I asked kmalloc for a negative number of bytes.
Imagine that. Allocating negative memory. That would be a crazy world.

Allocating specific address in Linux

I would like to allocate a memory in Linux in process at a specific address.
Actually I would like to do something like :
I will have number of process.
Each process will call an initialization function in a library (written by me) which will allocate some memory in address space of the process (which will store process related information). This will be done by each process
Once this memory is allocated, latter the program will call other function in the library. Now these function would like to access the memory allocated (containing process related information) by the first function.
The problem is that i cannot store the address of the memory allocated in the process address space in library (not even in static pointer as there are number of process) and i don't even want user program to store that address. I just don't want user program to know that there is memory allocated by library in their address space. Library function will be abstraction for them and they have to just use them.
Is it possible to to over come this problem.
I was thinking like, whenever any process calls initialization function of library which allocates memory , the memory always gets allocated at same address(say 10000) in all the process irrespective of all other things .
So that any library function which wants to access that memory can easily do by :
char *p=10000;
and then access, which will be access into the address space of the process which called the library function.
Not 100% I got what you are aiming for, but if you want to map memory into a specific set address you can use the MAP_FIXED flag to mmap():
"When MAP_FIXED is set in the flags argument, the implementation is informed that the value of pa shall be addr, exactly. If MAP_FIXED is set, mmap() may return MAP_FAILED and set errno to [EINVAL]. If a MAP_FIXED request is successful, the mapping established by mmap() replaces any previous mappings for the process' pages in the range [pa,pa+len)."
See mmap man page: http://linux.die.net/man/3/mmap
Your question doesnt make sense. As you have worded your question, a global variable in your library would work fine.
Maybe you are saying "a single process might load/unload your library and then load the library again and want the address on the second load". Maybe you are saying "there are 2 libraries and each library needs the same address". Simple. Use setenv() and getenv(). These will store/retrieve anything that can be represented as a string in a variable that has PROCESS WIDE SCOPE....i.e all libraries can see the same environment variables. Simply convert your address to a string (itoa), use setenv() to save it in an environment variable named "__SuperSecretGlobalAddress__", and then use getenv() to retrieve the value.
When your program starts up, a copy of the shell's environment is made for your process. getenv and setenv access and modify that copy. You cannot change the shell's environment with these functions.
See this post.

What is SEGV_MAPERR?

What is SEGV_MAPERR, why does it always come up with SIGSEGV?
There are two common kinds of SEGV, which is an error that results from an invalid memory access:
A page was accessed which had the wrong permissions. E.g., it was read-only but your code tried to write to it. This will be reported as SEGV_ACCERR.
A page was accessed that is not even mapped into the address space of the application at all. This will often result from dereferencing a null pointer or a pointer that was corrupted with a small integer value. This is reported as SEGV_MAPERR.
Documentation of a sort (indexed Linux source code) for SEGV_MAPERR is here: https://elixir.bootlin.com/linux/latest/A/ident/SEGV_MAPERR.
It's a segmentation fault. Most probably a dangling pointer issue, or some sort of buffer overflow.
SIGSSEGV is the signal that terminates it based on the issue, segmentation fault.
Check for dangling pointers as well as the overflow issue.
Enabling core dumps will help you determine the problem.

Resources