Why does the stack have to be page aligned? - linux

In Linux, I've tried (just for fun) to modify the kernel source in process.c create a stack address that has more entropy, i.e. in particular the line:
sp -= get_random_int() % 8192;
When I change this too much, the kernel halts or I get some seemingly undefined behavior. I'm guessing that this causes PAGE_ALIGN() to fail in some way? I'm not that interested in why PAGE_ALIGN() in particular fails, or exactly what piece of code in the kernel that fails (although that too would be nice to know); I'm more interested in why the stack must reside in a particular region at all. What is the architectural reason and motivation behind this? Does this have something to do with how GDT/LDT works in protected mode?
Just to make clear what I'm asking:
Why does the stack have to have the form 0xbfXXXXXX (on 32-bit)? Why cannot the stack be e.g. 0xaaXXXXXX, or any other value?

There is a limit in do_page_fault() as to how far outside the stack vma you can be before it considers it a bad access, perhaps you're hitting that?

Related

Stack location in Linux with ASLR

In Linux, with ASLR enabled, is there a range of addresses where user stack address lies? What about heap, instruction addresses(text section)?
In general, is it possible to look at an address and tell if it is for data or for code?
Edit:
I am trying to write a Pintool that looks at the EIP after a return and checks if the EIP points to a data area. Let's assume that NX is not enabled on this system.
For some reason, this was downvoted. Fortunately, the answer can be found here:
https://security.stackexchange.com/questions/185315/stack-location-range-on-linux-for-user-process/185330#185330
cat /proc/self/maps will show the initial location of the main thread's stack. This can be inaccurate for (at least) the following reasons:
you're not in the main thread
any part of the program was built with the -fsplit-stack option, or you call a library that does something similar
you're within a signal handler that requests the sigaltstack stack instead
you do weird alloca tricks like CHICKEN Scheme does to use the stack as a heap
...
Also note that the general areas are not fully random. See the AddressSanitizer project for something that takes advantage of this.

Can anyone explain why NO-OP slide is used in shelllcoding?

An example where NO-OP slide is a must for the exploit to work would be really helpful.
An example of when it is a must is when you want an exploit to be portable when targeting a non-ASLR enabled executable/system. Consider a local privilege escalation exploit where you return to shellcode on the stack. Because the stack holds the environment, the shellcode on the stack will be at slightly different offsets from the top of the stack when executing from within different users' shells, or on different systems. By prefixing the shellcode with, for example, 64k nop instructions, you provide a large margin of error for the stack address since your code will execute the same whether you land on the first nop or the last one.
Using nops is generally not as useful when targeting ASLR enabled systems since data sections will be mapped in entirely different areas of memory

Execute code in process's stack, on recent Linux

I want to use ptrace to write a piece of binary code in a running process's stack.
However, this causes segmentation fault (signal 11).
I can make sure the %eip register stores the pointer to the first instruction that I want to execute in the stack. I guess there is some mechanism that linux protects the stack data to be executable.
So, does anyone know how to disable such protection for stack. Specifically, I'm trying Fedora 15.
Thanks a lot!
After reading all replies, I tried execstack, which really makes code in stack executable. Thank you all!
This is probably due to the NX bit on modern processors. You may be able to disable this for your program using execstack.
http://advosys.ca/viewpoints/2009/07/disabling-the-nx-bit-for-specific-apps/
http://linux.die.net/man/8/execstack
As already mentioned it is due to the NX bit. But it is possible. I know for sure that gcc uses it itself for trampolines (which are a workaround to make e.g. function pointers of nested functions). I dont looked at the detailes, but I would recommend a look at the gcc code. Search in the sources for the architecture specific macro TARGET_ASM_TRAMPOLINE_TEMPLATE, there you should see how they do it.
EDIT: A quick google for that macro, gave me the hint: mprotect is used to change the permissions of the memory page. Also be carefull when you generate date and execute it - you maybe have in addition to flush the instruction cache.

Can I write-protect every page in the address space of a Linux process?

I'm wondering if there's a way to write-protect every page in a Linux
process' address space (from inside of the process itself, by way of
mprotect()). By "every page", I really mean every page of the
process's address space that might be written to by an ordinary
program running in user mode -- so, the program text, the constants,
the globals, and the heap -- but I would be happy with just constants,
globals, and heap. I don't want to write-protect the stack -- that
seems like a bad idea.
One problem is that I don't know where to start write-protecting
memory. Looking at /proc/pid/maps, which shows the sections of memory
in use for a given pid, they always seem to start with the address
0x08048000, with the program text. (In Linux, as far as I can tell,
the memory of a process is laid out with the program text at the
bottom, then constants above that, then globals, then the heap, then
an empty space of varying size depending on the size of the heap or
stack, and then the stack growing down from the top of memory at
virtual address 0xffffffff.) There's a way to tell where the top of
the heap is (by calling sbrk(0), which simply returns a pointer to the
current "break", i.e., the top of the heap), but not really a way to
tell where the heap begins.
If I try to protect all pages from 0x08048000 up to the break, I
eventually get an mprotect: Cannot allocate memory error. I don't know why mprotect would be
allocating memory anyway -- and Google is not very helpful. Any ideas?
By the way, the reason I want to do this is because I want to create a
list of all pages that are written to during a run of the program, and
the way that I can think of to do this is to write-protect all pages,
let any attempted writes cause a write fault, then implement a write
fault handler that will add the page to the list and then remove the write
protection. I think I know how to implement the handler, if only I could
figure out which pages to protect and how to do it.
Thanks!
You recieve ENOMEM from mprotect() if you try to call it on pages that aren't mapped.
Your best bet is to open /proc/self/maps, and read it a line at a time with fgets() to find all the mappings in your process. For each writeable mapping (indicated in the second field) that isn't the stack (indicated in the last field), call mprotect() with the right base address and length (calculated from the start and end addresses in the first field).
Note that you'll need to have your fault handler already set up at this point, because the act of reading the maps file itself will likely cause writes within your address space.
Start simple. Write-protect a few page and make sure your signal handler works for these pages. Then worry about expanding the scope of the protection. For example, you probably do not need to write-protect the code-section: operating systems can implement write-or-execute protection semantics on memory that will prevent code sections from ever being written to:
http://en.wikipedia.org/wiki/Self-modifying_code#Operating_systems

Why sometimes the call stack in a dump file does not looks correct?

Recently We have a production issue with application freezed, we tried to break in and analyse the dump file, unfortunately the call stack for the dump file does not looks good and hard to track down the cause of the freeze.
Two reasons why a call stack might look incorrect:
The stack might be corrupted. If the stack was corrupted for some reason (for instance, due to an overflow of a buffer which was allocated on the stack), all the stack frames are destroyed. This makes it impossible to compute the list of callers.
The symbols you use (if any) might not be appropriate for the binary which crashed. You need to use the exact same symbols which were used when compiling the binary. A slight change to the source code can render all the symbols invalid.
If the application hung rather than crashed, try loading into windbg and run !analyze -v -hang or try using adplus in hang mode. This tries to determine the cause of the hang which should give you a more meaningful call stack. The !locks command can be useful too if you have deadlock by showing you what is blocking on a resource.
If you call into the Windows API's, which then call back into you on the same thread (via Windows message handlers, for instance), it is not uncommon for the operations in the Windows DLL's to use stack conventions that the debugger cannot interpret. There's no requirement that the stack be traceable all the time during the execution of a c/c++ function/method, the stack-related registers can be re-used for other purposes and the standard places of stashing stack information can be ignored. I see this a lot in Windows.

Resources