SIGSEV error (gdb) - gdb

I currently am running a c++ file which compiles but crashes when it runs.
I open the debugger and get the following line when I run the program:
Program received signal SIGSEGV, Segmentation fault.
0xff0ab210 in strcat () from /lib/libc.so.1
I have no idea what that line means.
Can you explain?
Edit:
I have gotten responses telling me about how I used strcat in the program.
All I have used it for is to be used in par with the atoi method in order to convert a string to hex number.
Edit2:
I have seen something on the code that uses the strcat library, it's the .append function. Would that be the cause of the problem?

That's a segmentation fault. Usually it means you're trying to access memory that hasn't been allocated. Since you're using strcat I'm guessing that the destination string hasn't been allocated or not enough memory has been allocated.

If the seg fault comes from strcat, then it is likely one of the following happened:
Your source is a non-null terminated C string (malformed string).
The amount of memory allocated in the destination string is not enough to store both the source and the destination + 1 (the null at the end).
Check to see if both cases are covered and hopefully you won't see the SIGSEGV again.

Related

When and how exactly is a segmentation fault of a C/C++ application reported and handled by the OS?

I'm failing to understand a specific scenario in which my C++ multi-threaded application (running on a Linux machine, Wind River 6.x) is facing a segmentation fault.
I know the concept of segmentation fault and even went over this post and also this one but failed to encounter a scenario similar to mine and/or an answer to my question, so I'm posting this question.
My code that generates the segmentation fault is as follows (abbreviated and simplified):
// MyStruct* pMyStruct is a function argument that arrives to the function and at some point of time
// being set to NULL
ASSERT_PTR_NE(pMyStruct, NULL); <--- this assertion is logged to my application log (meaning, at this line, pMyStruct is NULL)
int someInt = pMyStruct->someIntOfMyStruct; <--- this line does NOT create the segmentation fault
double someDouble = pMyStruct->someDoubleOfMyStruct; <--- this line ALSO does NOT create the segmentation fault
ASSERT_NUM_EQ(pMyStruct->someIntOfMyStruct, SOME_INT_VALUE_TO_CHECK); <--- this line DOES create the segmentation fault
As mentioned in the last code line, the 4th line of code is the "last line" that my application is executing (I guess) --> when examining the core file with GDB, frame 0 of the core file indicates that this line is the line that causes the crash.
My questions are if so:
How come the 2nd and 3rd lines of code of my application did not cause segmentation fault?
What exactly takes place, system wise, i.e. - in the OS and the application from the moment the NULL was accessed (in the first line) until the application is being terminated by the OS?
Meaning, is it possible that indeed the actual segmentation fault was raised due to the 1st line, YET, for some reason, until the OS actually took the decision and action to terminate the application, also lines 2-4 were executed and when arriving to the 4th line the application "again" raised segmentation fault?
Or, perhaps, is it possible that what actually took place here is an overrun of the pMyStruct variable - meaning, after the first line that does the assert (and prints info to the log file of the application) another thread set the pMyStruct to NON NULL value, thus "allowing" lines 2-3 to run WITHOUT causing a crash and then JUST before line 4 was executed the pMyStruct was "overrun" by another thread and was set to NULL thus, this time causing line 4 to crash?
Typically, an OS creates a segmentation fault after the CPU faults on an address. The CPU doesn't know why the fault happened. It might be that the memory is paged out to disk, but for this question we're assuming a bad pointer. The OS knows it's a bad pointer because the address doesn't correspond to any paged-out memory. Hence, the OS tells the CPU it is handling the situation, and tells the CPU to continue execution in the signal handler.
The C++ null pointer isn't special to the CPU. It just so happens that the OS by convention does not allocate RAM at this address.
By C++ standards, your code has Undefined Behavior, and that allows "time travel". More accurately, to allow optimizations, compilers may shuffle around code in the assumption that Undefined Behavior does not happen. It would seem that lines 2 & 3 are shuffled after line 4. You can't detect this in a correct C++ program.
This is not how a typical CPU sees it. Modern CPU's also shuffle around instructions internally, like compilers do, but when the CPU reports the fault to the OS it will pretend that all instructions happened in the right order.

What does <exp+6> mean in gdb?

I was debugging a C++ code using gdb. The program stopped due to a segmentation fault.
Program received signal SIGSEGV, Segmentation fault.
So I was trying to print out the value of variables to identify where the error is coming from. I have an array called 'ring' of type 'Link **', where Link is a class I defined. Each element in the array points to a 'Link *' variable. Here is the output when I print the first three elements of the 'ring' array.
(gdb) print ring[0]
$13 = (Link *) 0x8125290
(gdb) print ring[1]
$14 = (Link *) 0xb7e80b86 <exp+6>
(gdb) print ring[2]
$15 = (Link *) 0x8132e20
Why am I getting '' after the memory address when printing 'ring[1]'? What does it mean?
EDIT: Im using gdb 7.8 on Arch Linux (3.16.4-1-ARCH)
It means the pointer value is equal to the address of the exp symbol plus 6. It's just the debugger trying to be helpful—whenever it decodes any pointer value, it tries to see if the pointer happens to lie near any known symbols in the object code, and it prints out that information if so.
You might expect to see such notation when examining the disassembly of a function's code, e.g. in branch targets, but as a data pointer, that's very unusual (function pointers would tend to point directly at function symbols, not offset into them).
You almost certainly have some kind of memory corruption bug that just happens to produce that value as a side effect.

Protect the whole address space using mprotect

For my university project I need to WRITE protect the whole address space of the process. I was reading the /proc/self/maps file and parsing the mapping.
So for each entry of the format 08048000-0804c000 r-xp 00000000 08:03 7971106 /bin/cat, I am reading the first two entry(here 08048000 & 0804c000), converting them to decimal. Lets assume the decimal equivalent is A & B respectively. Then I do mprotect((int*)A, B-A, PROT_READ). But this approach is giving me segmentation fault. I can't find out what I did wrong here. May be I've some knowledge gap here which is causing the problem. Someone can give me some suggestions?
Assuming that your implementation is correct, I'd still expect to see segmentation faults.
After all, you're telling the kernel that you don't want to be allowed to write to any part of your memory. Afterwards, you'll just continue to run your process and the next time you try to write anything at all you'll get a segmentation fault because that's no longer allowed.
That'll most likely be when you return from mprotect() after "protecting" the stack.
Thinking a bit more, it's even possible that you're getting segmentation faults while executing memory (i.e. a shared lib, or your executable code) after you've "protected" it.
In fact, all of the bits of memory where it's safe to apply read-only / do-not-execute flags already have those flags set.
I suspect that's the insight this univerity project was meant to give you.

Buffer array overflow in for loop in c

When would a program crash in a buffer overrun case
#include<stdio.h>
#include<stdlib.h>
main() {
char buff[50];
int i=0;
for( i=0; i <100; i++ )
{
buff[i] = i;
printf("buff[%d]=%d\n",i,buff[i]);
}
}
What will happen to first 50 bytes assigned, when would the program crash?
I see in my UBUNTU with gcc a.out it is crashing when i 99
>>
buff[99]=99
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
<<
I would like to know why this is not crashing when assignment happening at buff[51] in the for loop?
It is undefined behavior. You can never predict when (or if at all) it crashes, but you cannot rely upon it 'not crashing' and code an application.
Reasoning
The rationale is that there is no compile or run time 'index out of bound checking' in c arrays. That is present in STL vectors or arrays in other higher level languages. So whenever your program accesses memory beyond the allocated range, it depends whether it simply corrupts another field on your program's stack or affects memory of another program or something else, so one can never predict a crash which only occurs in extreme cases. It only crashes in a state that forces the OS to intervene OR when it no longer remains possible for your program to function correctly.
Example
Say you were inside a function call, and immediately next to your array was, the RETURN address i.e. the address your program uses to return to the function it was called from. Suppose you corrupted that and now your program tries to return to the corrupted value, which is not a valid address. Hence it would crash in such a situation.
The worst happens when you silently modified another field's value and didn't even discover what was wrong assuming no crash occurred.
Since it seems you have allocated on the stack the buffer, the app possibly will crash on the first occasion you overwrite an instruction which is to be executed, possibly somewhere in the code of the for loop... at least that's how it's supposed to be in theory.

Why am I not getting a segmentation fault with this code? (Bus error)

I had a bug in my code that went like this.
char desc[25];
char name[20];
char address[20];
sprintf (desc, "%s %s", name, address);
Ideally this should give a segfault. However, I saw this give a bus error.
Wikipedia says something to the order of 'Bus error is when the program tries to access an unaligned memory location or when you try to access a physical (not virtual) memory location that does not exist or is not allowed. '
The second part of the above statement sounds similar to a seg fault. So my question is, when do you get a SIGBUS and when a SIGSEGV?
EDIT:-
Quite a few people have mentioned the context. I'm not sure what context would be needed but this was a buffer overflow lying inside a static class function that get's called from a number of other class functions. If there's something more specific that I can give which will help, do ask.
Anyways, someone had commented that I should simply write better code. I guess the point of asking this question was "can an application developer infer anything from a SIGBUS versus a SIGSEGV?" (picked from that blog post below)
As you probably realize, the base cause is undefined behavior in your
program. In this case, it leads to an error detected by the hardware,
which is caught by the OS and mapped to a signal. The exact mapping
isn't really specified (and I've seen integral division by zero result
in a SIGFPE), but generally: SIGSEGV occurs when you access out of
bounds, SIGBUS for other accessing errors, and SIGILL for an illegal
instruction. In this case, the most likely explination is that your
bounds error has overwritten the return address on the stack. If the
return address isn't correctly aligned, you'll probably get a SIGBUS,
and if it is, you'll start executing whatever is there, which could
result in a SIGILL. (But the possibility of executing random bytes as
code is what the standards committee had in mind when they defined
“undefined behavior”. Especially on machines with no memory
protection, where you could end up jumping directly into the OS.)
A segmentation fault is never guaranteed when you're doing fishy stuff with memory. It all depends on a lot of factors (how the compiler lays out the program in memory, optimizations etc).
What may be illegal for a C++ program may not be illegal for a program in general. For instance the OS doesn't care if you step outside an array. It doesn't even know what an array is. However it does care if you touch memory that doesn't belong to you.
A segmentation fault occurs if you try to do a data access a virtual address that is not mapped to your process. On most operating systems, memory is mapped in pages of a few kilobytes; this means that you often won't get a fault if you write off the end of an array, since there is other valid data following it in the memory page.
A bus error indicates a more low-level error; a wrongly-aligned access or a missing physical address are two reasons, as you say. However, the first is not happening here, since you're dealing with bytes, which have no alignment restriction; and I think the second can only happen on data accesses when memory is completely exhausted, which probably isn't happening.
However, I think you might also get a bus error if you try to execute code from an invalid virtual address. This could well be what is happening here - by writing off the end of a local array, you will overwrite important parts of the stack frame, such as the function's return address. This will cause the function to return to an invalid address, which (I think) will give a bus error. That's my best guess at what particular flavour of undefined behaviour you are experiencing here.
In general, you can't rely on segmentation faults to catch buffer overruns; the best tool I know of is valgrind, although that will still fail to catch some kinds of overrun. The best way to avoid overruns when working with strings is to use std::string, rather than pretending that you're writing C.
In this particular case, you don't know what kind of garbage you have in the format string. That garbage could potentially result in treating the remaining arguments as those of an "aligned" data type (e.g. int or double). Treating an unaligned area as an aligned argument definitely causes SIGBUS on some systems.
Given that your string is made up of two other strings each being a max of 20 characters long, yet you are putting it into a field that is 25 characters, that is where your first issue lies. You are have a good potential to overstep your bounds.
The variable desc should be at least 41 characters long (20 + 20 + 1 [for the space you insert]).
Use valgrind or gdb to figure out why you are getting a seg fault.
char desc[25];
char name[20];
char address[20];
sprintf (desc, "%s %s", name, address);
Just by looking at this code, I can assume that name and address each can be 20 chars long. If that is so, then does it not imply that desc should be minimum 20+20+1 chars long? (1 char for the space between name and address, as specified in the sprintf).
That can be the one reason of segfault. There could be other reasons as well. For example, what if name is longer than 20 chars?
So better you use std::string:
std::string name;
std::string address;
std::string desc = name + " " + address;
char const *char_desc = desc.str(); //if at all you need this