How do I find the address of an EXC_BAD_ACCESS exception? - ios

In How do I recover from EXC_BAD_ACCESS?, I figured out how to recover from an EXC_BAD_ACCESS, but I had the badly accessed pointer stored in a global. Obviously, this won't scale. When I run the code in the iOS Simulator (i386), I can see faultvaddr register in the Exception State Registers section of the debugger when inside my catch_exception_raise function. However, its value isn't the same or close to pointer returned from vm_allocate. Is there a way to get this value dynamically?
Given the catch_exception_raise function below, how would I discover the address that caused the EXC_BAD_ACCESS?
kern_return_t
catch_exception_raise(mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code_vector,
mach_msg_type_number_t code_count)
{
fprintf(stderr, "catch_exception_raise %d\n", exception);
return KERN_SUCCESS;
}

There is a great amount of detail on that in the OS X and iOS Internals book (http://www.newosxbook.com). Listing 11-21 (ibid) in the book actually shows sample code to do so. In a nutshell, you've two options:
A) look at the exception itself from the exception data - convert the state to an arm_thread_state, something like so:
struct arm_thread_state *atsh = &exc.old_state;
printf ("CPSR is %p, PC is %p, etc.\n", atsh->cpsr, atsh->pc);
Or
B) call thread_get_state to the thread port (since you have that right there as argument #2), and get pc (the instruction pointer) or any of the other registers
EDIT
I'm not sure how to make A) work, but the following works (found here) for B) on the 32-bit iOS Simulator. I'm not sure what the arm register equivalent is for __faultvaddr, so you'd have to figure that out before trying arm.
// types from thread_status.h
x86_exception_state32_t x86_exception_state32;
mach_msg_type_number_t sc = x86_EXCEPTION_STATE32_COUNT;
thread_get_state(thread,
x86_EXCEPTION_STATE32,
(thread_state_t)&x86_exception_state32,
&sc);

Related

Where does a segmentation fault occur if the debugger points to a function definition?

To elaborate, I am currently writing a program that requires a function that is provided by the professor. When I run the program, I get a segmentation fault, and the debugger I use (gdb) says that the segmentation fault occurred at the definition of the function that, like I said, was provided by the professor.
So my question here is, is the definition itself causing the fault, or is it somewhere else in the program that called the function causing the fault?
I attempted to find a spot in the program that might have been leading to it, such as areas that might have incorrect parameters. I have not changed the function itself, as it is not supposed to be modified (as per instructions). This is my first time posting a question, so if there is any other information needed, please let me know.
The error thrown is as follows:
Program received signal SIGSEGV, Segmentation fault. .0x00401450 in Parser::GetNextToken (in=..., line=#0x63fef0: 1) at PA2.cpp:20 20 return GetNextToken(in, line);
The code itself that this is happening at is this:
static LexItem GetNextToken(istream& in, int& line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return GetNextToken(in, line);
}
Making many assumptions here, but maybe the lesson is to understand how the stack is affected by a function call and parameters. Create a main() function, that call the professor's provided function and trace the code using dbg, looking at the stack.

RUST error ENOMEM in call of posix_memalign into attached program

I'll try to summarize but it's gonna be complicated.
I'm having an operating system course in my university, and i have a lab work to do.
I'm working in Rust (the lab work is said to be doable in any compiled language but was principally designed for C in the first time).
So I have a tracer program and a traced program.
The goal of this step of the lab work is to attach from the tracer to the traced with ptrace, then to inject "trap-call-trap" instructions at the good place to replace an existing useless function, with the function posix_memalign (from the libc) in the traced, by an indirect call via registers (with rax). The goal is to allocate memory to be able later to call a cache code from another file into the traced program.
The problem i have is that i achieve to do a posix memalign in the tracer so i know the function works, but when i call it in the traced (via the tracer), and look in register rax for the return of the function, i always get a "12" which corresponds to ENOMEM (ENOMEM Not enough space/cannot allocate memory).
I have 2 separated cargo projects to be able to launch each program separately from cargo.
Everything is on this git : https://github.com/Carrybooo/TP_SEL
I'm sorry all prints and outputs are in french, (some comments too, i'm in a french course) and i didn't think i would have to share it with anyone. There is a lot of useless code too in it, from the previous steps of the lab, that i have kept just in case, so my code is not really clean.
This is the part where i attach and modify the regs to call the function (I shortened the code and didn't show you the auxiliaries functions declarations cause it would be too long) :
ptrace::attach(pid_ptrace) //attaching to process
wait(); //wait after attaching
inject(pid_trace, offset_fct_to_replace, false); //injecting trap-call-trap
ptrace::cont(pid_ptrace, Signal::SIGCONT);
wait(); //wait for 1st trap
let mut regs =
ptrace::getregs(pid_ptrace);
let ptr_to_ptr: *mut *mut c_void = ptr::null_mut();
regs.rax = get_libc_address(pid_trace).unwrap() + get_libc_offset("posix_memalign").unwrap();
regs.rsp = regs.rsp - (size_of::<*mut *mut c_void>() as u64);
regs.rdi = ptr_to_ptr as u64;
regs.rsi = size_of::<usize>() as u64;
regs.rdx = size_of::<usize>() as u64;
ptrace::setregs(pid_ptrace, regs); //set regs with modification
ptrace::cont(pid_ptrace, Signal::SIGCONT);
wait();
let regs = ptrace::getregs(pid_ptrace);
ptrace::detach(pid_ptrace, Signal::SIGCONT) //detaching
And running the program in the terminal gives something like this :
before modification of regs:
rax = 6
rip = 55e6c932ddc1
rsp = 7ffcee0b7fb8
before function execution:
rax = 7f59b935ded0
rdi = 0
rip = 55e6c932ddc1
rsp = 7ffcee0b7fb0
after function execution:
rax = 12 <------//RESULT OF THE CALL IS HERE
rdi = 55e6cac6aba0
rip = 7f59b935df20
rsp = 7ffcee0b7f90
//end of program
So yeah i don't know why i keep getting an error on this call, i presume it's because it violates rust memory safety, because the compiler never knew in the traced program that it would have to allocate memory, but i'm not sure of it, neither how to bypass it.
I hope that i've been clear enough, let me know if you need any more detail, and i really thank in advance anyone who could help me. Every advice will be welcome.
So I went with the libc memalign instead of using posix_memalign. It's not as restricted, and it works well while calling with registers in the traced program.
Still no idea of why posix_memalign doesn't work while called from the regs in a rust program.

how to fix "malloc: can't protect region for postlude guard page" warnings on iOS

I'm developing an iOS app and when I run it on my devices I got lots of the following warnings:
MyApp(2138,0x104338000) malloc: *** can't protect(0x3) region for postlude guard page at 0x104950000
They don't stop the execution but looks scary and probably are related to occasional crash of my app. I googled and only found two pages on the entire web and none of the helps. I wonder if anyone here knows how to fix this?
Edit: here is the product scheme I used:
The error you're seeing comes from Apple's malloc implementation and is due to vm_protect failing when trying modify memory protection of the guard pages that have been added to your memory allocations.
So it sounds like you've enabled debugmalloc's MallocGuardEdges flag (I didn't think debugmalloc was available on ios devices).
The 0x3 = VM_PROT_READ | VM_PROT_WRITE in the message is saying that vm_protect failed to make the page read-write which means that this is happening in response to a free.
The only documented return codes for vm_protect are KERN_PROTECTION_FAILURE and KERN_INVALID_ADDRESS so at this point I can only guess what happened. Making a page read-write seems like a modest request, for a valid page you wouldn't expect KERN_PROTECTION_FAILURE, which leaves KERN_INVALID_ADDRESS, meaning that perhaps your page at 0x104950000 is invalid.
Which would imply a memory stomping bug.
The issue is one-year old, but we ran into the same issue and found this thread. We where able to simplify and reproduce it in latest Xcode 7.3 on Mac with the following piece of C code:
int main(int argc, char *argv[])
{
const int s = 100, n = 5000;
int i;
void *p = malloc(s);
for (i = 2 ; i <= n ; i++)
p = realloc(p,i * s);
for (i = n - 1 ; i > 0 ; i--)
{
void *newp = realloc(p,i * s);
if (newp != p)
printf("realloc(p,%d * %d = %d) changes pointer from %p to %p\n",i,s,i * s,p,newp);
p = newp;
}
free(p);
return 0;
}
This will trigger the malloc_printf() breakpoint in the 2nd for loop (when the reallocations shrink memory) and print:
malloc: *** can't protect(0x3) region for postlude guard page at 0x48ed000
It appears (setting a breakpoint on malloc_printf()) that this happens exactly on the first time that realloc() changes the returned pointer, the total output of above program is:
realloc(p,1249 * 100 = 124900) changes pointer from 0x48b0000 to 0x5000000
realloc(p,2 * 100 = 200) changes pointer from 0x5000000 to 0x240cc60
Playing a bit with combinations of the block size s and number of iterations n it happens at least for 10/50000, 100/5000, 200/5000, ..., it seems when the allocated memory i * s shrinks to around 124000 bytes. Other combinations like 1/200000 don't trigger malloc_printf().
Given the simplicity of this code snippet, we believe that this is a bug in Apple's malloc debug implementation.... or the message is supposed to be some informative (internal) message rather than trying to signal a real memory issue.
(A version of) the source code for Apple's malloc implementation can be found here http://www.opensource.apple.com/source/Libc/Libc-391.4.2/gen/scalable_malloc.c?txt. We are considering to raise with Apple Developer Centre...
So in short the answer is that it might very well not be a memory stomping bug in your code, but instead an issue in de malloc debug code itself, in which case you need to just ignore the message.

Passing Data through the Stack

I wanted to see if you could pass struct through the stack and I manage to get a local var from a void function in another void function.
Do you guys thinks there is any use to that and is there any chance you can get corrupted data between the two function call ?
Here's the Code in C (I know it's dirty)
#include <stdio.h>
typedef struct pouet
{
int a,b,c;
char d;
char * e;
}Pouet;
void test1()
{
Pouet p1;
p1.a = 1;
p1.b = 2;
p1.c = 3;
p1.d = 'a';
p1.e = "1234567890";
printf("Declared struct : %d %d %d %c \'%s\'\n", p1.a, p1.b, p1.c, p1.d, p1.e);
}
void test2()
{
Pouet p2;
printf("Element of struct undeclared : %d %d %d %c \'%s\'\n", p2.a, p2.b, p2.c, p2.d, p2.e);
p2.a++;
}
int main()
{
test1();
test2();
test2();
return 0;
}
Output is :
Declared struct : 1 2 3 a '1234567890'
Element of struct undeclared : 1 2 3 a '1234567890'
Element of struct undeclared : 2 2 3 a '1234567890'
Contrary to the opinion of the majority, I think it can work out in most of the cases (not that you should rely on it, though).
Let's check it out. First you call test1, and it gets a new stack frame: the stack pointer which signifies the top of the stack goes up. On that stack frame, besides other things, memory for your struct (exactly the size of sizeof(struct pouet)) is reserved and then initialized. What happens when test1 returns? Does its stack frame, along with your memory, get destroyed?
Quite the opposite. It stays on the stack. However, the stack pointer drops below it, back into the calling function. You see, this is quite a simple operation, it's just a matter of changing the stack pointer's value. I doubt there is any technology that clears a stack frame when it is disposed. It's just too costy a thing to do!
What happens then? Well, you call test2. All it stores on the stack is just another instance of struct pouet, which means that its stack frame will most probably be exactly the same size as that of test1. This also means that test2 will reserve the memory that previously contained your initialized struct pouet for its own variable Pouet p2, since both variables should most probably have the same positions relative to the beginning of the stack frame. Which in turn means that it will be initialized to the same value.
However, this setup is not something to be relied upon. Even with concerns about non-standartized behaviour aside, it's bound to be broken by something as simple as a call to a different function between the calls to test1 and test2, or test1 and test2 having stack frames of different sizes.
Also, you should take compiler optimizations into account, which could break things too. However, the more similar your functions are, the less chances there are that they will receive different optimization treatment.
Of course there's a chance you can get corrupted data; you're using undefined behavior.
What you have is undefined behavior.
printf("Element of struct undeclared : %d %d %d %c \'%s\'\n", p2.a, p2.b, p2.c, p2.d, p2.e);
The scope of the variable p2 is local to function test2() and as soon as you exit the function the variable is no more valid.
You are accessing uninitialized variables which will lead to undefined behavior.
The output what you see is not guaranteed at all times and on all platforms. So you need to get rid of the undefined behavior in your code.
The data may or may not appear in test2. It depends on exactly how the program was compiled. It's more likely to work in a toy example like yours than in a real program, and it's more likely to work if you turn off compiler optimizations.
The language definition says that the local variable ceases to exist at the end of the function. Attempting to read the address where you think it was stored may or may produce a result; it could even crash the program, or make it execute some completely unexpected code. It's undefined behavior.
For example, the compiler might decide to put a variable in registers in one function but not in the other, breaking the alignment of variables on the stack. It can even do that with a big struct, splitting it into several registers and some stack — as long as you don't take the address of the struct it doesn't need to exist as an addressable chunk of memory. The compiler might write a stack canary on top of one of the variables. These are just possibilities at the top of my head.
C lets you see a lot behind the scenes. A lot of what you see behind the scenes can completely change from one production compilation or run to the next.
Understanding what's going on here is useful as a debugging skill, to understand where values that you see in a debugger might be coming from. As a programming technique, this is useless since you aren't making the computer accomplish any particular result.
Just because this works for one compiler doesn't mean that it will for all. How uninitialized variables are handled is undefined and one computer could very well init pointers to null etc without breaking any rules.
So don't do this or rely on it. I have actually seen code that depended on functionality in mysql that was a bug. When that was fixed in later versions the program stopped working. My thoughts about the designer of that system I'll keep to myself.
In short, never rely on functionality that is not defined. If you knowingly use it for a specific function and you are prepared that an update to the compiler etc can break it and you keep an eye out for this at all times it might be something you could explain and live with. But most of the time this is far from a good idea.

"EXC_BAD_ACCESS" vs "Segmentation fault". Are both same practically?

In my first few dummy apps(for practice while learning) I have come across a lot of EXC_BAD_ACCESS, that somehow taught me Bad-Access is : You are touching/Accessing a object that you shouldn't because either it is not allocated yet or deallocated or simply you are not authorized to access it.
Look at this sample code that has bad-access issue because I am trying to modify a const :
-(void)myStartMethod{
NSString *str = #"testing";
const char *charStr = [str UTF8String];
charStr[4] = '\0'; // bad access on this line.
NSLog(#"%s",charStr);
}
While Segmentation fault says : Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory (more description here.
I wanna know two things.
One, Am I right about objective-C's EXC_BAD_ACCESS ? Do I get it right ?
Second, Are EXC_BAD_ACCESS and Segmentation fault same things and Apple has just improvised its name?
No, EXC_BAD_ACCESS is not the same as SIGSEGV.
EXC_BAD_ACCESS is a Mach exception (A combination of Mach and xnu compose the Mac OS X kernel), while SIGSEGV is a POSIX signal. When crashes occur with cause given as EXC_BAD_ACCESS, often the signal is reported in parentheses immediately after: For instance, EXC_BAD_ACCESS(SIGSEGV). However, there is one other POSIX signal that can be seen in conjunction with EXC_BAD_ACCESS: It is SIGBUS, reported as EXC_BAD_ACCESS(SIGBUS).
SIGSEGV is most often seen when reading from/writing to an address that is not at all mapped in the memory map, like the NULL pointer, or attempting to write to a read-only memory location (as in your example above). SIGBUS on the other hand can be seen even for addresses the process has legitimate access to. For instance, SIGBUS can smite a process that dares to load/store from/to an unaligned memory address with instructions that assume an aligned address, or a process that attempts to write to a page for which it has not the privilege level to do so.
Thus EXC_BAD_ACCESS can best be understood as the set of both SIGSEGV and SIGBUS, and refers to all ways of incorrectly accessing memory (whether because said memory does not exist, or does exist but is misaligned, privileged or whatnot), hence its name: exception – bad access.
To feast your eyes, here is the code, within the xnu-1504.15.3 (Mac OS X 10.6.8 build 10K459) kernel source code, file bsd/uxkern/ux_exception.c beginning at line 429, that translates EXC_BAD_ACCESS to either SIGSEGV or SIGBUS.
/*
* ux_exception translates a mach exception, code and subcode to
* a signal and u.u_code. Calls machine_exception (machine dependent)
* to attempt translation first.
*/
static
void ux_exception(
int exception,
mach_exception_code_t code,
mach_exception_subcode_t subcode,
int *ux_signal,
mach_exception_code_t *ux_code)
{
/*
* Try machine-dependent translation first.
*/
if (machine_exception(exception, code, subcode, ux_signal, ux_code))
return;
switch(exception) {
case EXC_BAD_ACCESS:
if (code == KERN_INVALID_ADDRESS)
*ux_signal = SIGSEGV;
else
*ux_signal = SIGBUS;
break;
case EXC_BAD_INSTRUCTION:
*ux_signal = SIGILL;
break;
...
Edit in relation to another of your questions
Please note that exception here does not refer to an exception at the level of the language, of the type one may catch with syntactical sugar like try{} catch{} blocks. Exception here refers to the actions of a CPU on encountering certain types of mistakes in your program (they may or may not be be fatal), like a null-pointer dereference, that require outside intervention.
When this happens, the CPU is said to raise what is commonly called either an exception or an interrupt. This means that the CPU saves what it was doing (the context) and deals with the exceptional situation.
To deal with such an exceptional situation, the CPU does not start executing any "exception-handling" code (catch-blocks or suchlike) in your application. It first gives the OS control, by starting to execute a kernel-provided piece of code called an interrupt service routine. This is a piece of code that figures out what happened to which process, and what to do about it. The OS thus has an opportunity to judge the situation, and take the action it wants.
The action it does for an invalid memory access (such as a null pointer dereference) is to signal the guilty process with EXC_BAD_ACCESS(SIGSEGV). The action it does for a misaligned memory access is to signal the guilty process with EXC_BAD_ACCESS(SIGBUS). There are many other exceptional situations and corresponding actions, not all of which involve signals.
We're now back in the context of your program. If your program receives the SIGSEGV or SIGBUS signals, it will invoke the signal handler that was installed for that signal, or the default one if none was. It is rare for people to install custom handlers for SIGSEGV and SIGBUS and the default handlers shut down your program, so what you usually get is your program being shut down.
This sort of exceptions is therefore completely unlike the sort one throws in try{}-blocks and catch{}es. Those exceptions are handled purely within the application, without involving the OS at all. Here what happens is that a throw statement is simply a glorified jump to the inner-most catch block that handles that exception. As the exception bubbles through the stack, it unwinds the stack behind it, running destructors and suchlike as needed.
Basically yes, indeed an EXC_BAD_ACCESS is usually paired with a SIGSEGV which is a signal that warns about the segmentation failure.
A segmentation failure is risen whenever you are working with a pointer that points to invalid data (maybe not belonging to the process, maybe read-only, maybe an invalid address in general).
Don't think about the segmentation fault in terms of "accessing an object", you are accessing a memory location, so an address. That address must be considered coherent by the OS memory protection system.
Not all errors which are related to accessing invalid data can be tracked by the memory manager, think about a pointer to a stack allocated variable, which is considered valid although its content is not valid anymore upon restoring the stack frame.

Resources