How does gdb disable randomization for a single process? - gdb

I came from this link: Force gdb to load shared library at randomized address and I learned that gdb will disable ASLR for the current process.
But the only way I know to disable ASLR is to do it globally via echo 0 > /proc/sys/kernel/randomize_va_space.
Now I'm wondering how does gdb disable ASLR on startup, and only for the current process?
EDIT
As ssbssa suggested, I wrote a program to test it:
#include <stdio.h>
#include <unistd.h>
#include <sys/personality.h>
int main(int argc, char **argv)
{
char *argv2[] = { argv[0], "test", "\0" };
if (argc == 1)
{
char *data = malloc(20);
printf("pid %d\n", getpid());
printf("heap allocated at %p\n", data);
printf("system() at %p\n", system);
puts("exit in 100s");
sleep(100);
exit(0);
}
personality(ADDR_NO_RANDOMIZE);
execvp(argv2[0], argv2);
}
And the process map is:
# cat /proc/1997932/maps
00400000-00401000 r--p 00000000 fc:01 430424 /root/no-aslr
00401000-00402000 r-xp 00001000 fc:01 430424 /root/no-aslr
00402000-00403000 r--p 00002000 fc:01 430424 /root/no-aslr
00403000-00404000 r--p 00002000 fc:01 430424 /root/no-aslr
00404000-00405000 rw-p 00003000 fc:01 430424 /root/no-aslr
01352000-01373000 rw-p 00000000 00:00 0 [heap]
7f222f928000-7f222f94a000 r--p 00000000 fc:01 394264 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f222f94a000-7f222fac2000 r-xp 00022000 fc:01 394264 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f222fac2000-7f222fb10000 r--p 0019a000 fc:01 394264 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f222fb10000-7f222fb14000 r--p 001e7000 fc:01 394264 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f222fb14000-7f222fb16000 rw-p 001eb000 fc:01 394264 /usr/lib/x86_64-linux-gnu/libc-2.31.so

Related

ptrace fails when injecting code into old ELF binary (2005)

I have a very old gameserver file for a video-game that became obsolete years ago (more than a decade and a half has passed since then). A lot of clones and reverse-engineered copycats of this engine exist, but nothing will ever be like the real thing, or at least without tons and tons of work (it's a MMORPG server). It's so old that it uses LinuxThreads instead of NPTL, and uses it for its thread-per-connection architecture (up to 1100 simmultaneos connections interacting with a huge 2D tilebased game world).
I was trying to rewrite it from scratch, since it has ancient GCC debug info available, but had to drop it since the amount of work to do was insane. Now I'm trying to inject new functionality into it, but couldn't proggress any further since I don't really understand how I'm supposed to inject into it.
I've tried coding a very simple injector using ptrace, but the server dies because of a segmentation fault (SIGSEGV) and since I can't attach GDB, I don't really know where the crash is happening.
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#define EMPTY_ADDR 0x80EF000UL
const char *SHELLCODE = "\x90\x90\x90\x90\x90\x90\x90\x90";
pid_t GamePID;
void GetGamePID() {
FILE *fp = fopen("/home/bob/lock.pid", "rb");
if (!fp) {
printf(":: [Error] Game not running.\n");
return;
}
fscanf(fp, "%d", &GamePID);
}
int main() {
GetGamePID();
if (!GamePID)
return 0;
if (ptrace(PTRACE_ATTACH, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot attach.\n");
printf(":: # Fail %d: %s.\n", errno, strerror(errno));
return 0;
}
siginfo_t info;
waitid(P_PID, GamePID, &info, WSTOPPED);
printf(":: [Info] Attach on PID %d.\n", GamePID);
struct user_regs_struct oldregs, regs;
if (ptrace(PTRACE_GETREGS, GamePID, NULL, &oldregs)) {
printf(":: [Error] Cannot save registers (Fail %d).\n", errno);
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
unsigned long save[2];
save[0] = ptrace(PTRACE_PEEKTEXT, GamePID, (void *)(EMPTY_ADDR), NULL);
save[1] = ptrace(PTRACE_PEEKTEXT, GamePID, (void *)(EMPTY_ADDR + 8UL), NULL);
size_t payload_size = strlen(SHELLCODE);
uint64_t *payload = (uint64_t *)SHELLCODE;
printf("[*] Injecting payload at address 0x%lx.\n", EMPTY_ADDR);
for (size_t i = 0; i < payload_size; i += 8, payload++) {
if (ptrace(PTRACE_POKETEXT, GamePID, EMPTY_ADDR + i, *payload) < 0) {
printf(":: [Error] Failed to PTRACE_POKETEXT: %s\n", strerror(errno));
return 1;
}
}
regs = oldregs;
regs.rip = EMPTY_ADDR;
if (ptrace(PTRACE_SETREGS, GamePID, NULL, &regs)) {
printf(":: [Error] Cannot modify registers.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_CONT, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot run shellcode.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
waitid(P_PID, GamePID, &info, WSTOPPED);
// I used blank r-xp space but just in case...
if (ptrace(PTRACE_POKETEXT, GamePID, (void *)(EMPTY_ADDR), (void *)save[0]) ||
ptrace(PTRACE_POKETEXT, GamePID, (void *)(EMPTY_ADDR + 8UL), (void *)save[1])) {
printf(":: [Error] Cannot restore origcode.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_SETREGS, GamePID, NULL, &oldregs)) {
printf(":: [Error] Cannot restore registers.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_DETACH, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot detach from process.\n");
return 1;
}
puts("[+] Done.");
}
That's how my injector looks like. Strings and whatnot is hardcoded because this is dummy code. Here is /proc/pid/maps output:
08047000-08048000 rwxp 00000000 08:01 549662 /home/bob/bin/game.orig
08048000-08125000 r-xp 00001000 08:01 549662 /home/bob/bin/game.orig
08125000-08129000 rwxp 000dd000 08:01 549662 /home/bob/bin/game.orig
08129000-0eb45000 rwxp 00000000 00:00 0
0f3e2000-14f10000 rwxp 00000000 00:00 0 [heap]
c573f000-f7b69000 rwxp 00000000 00:00 0
f7b6a000-f7b71000 rwxs 00000000 00:01 32821 /SYSV0000271b (deleted)
f7b71000-f7b72000 rwxp 00000000 00:00 0
f7bb5000-f7beb000 rwxp 00000000 00:00 0
f7bec000-f7d3e000 rwxp 00000000 00:00 0
f7d3e000-f7e57000 r-xp 00000000 08:01 1041510 /home/bob/lib/libc.so.6
f7e57000-f7e59000 r-xp 00119000 08:01 1041510 /home/bob/lib/libc.so.6
f7e59000-f7e5b000 rwxp 0011b000 08:01 1041510 /home/bob/lib/libc.so.6
f7e5b000-f7e5d000 rwxp 00000000 00:00 0
f7e5d000-f7e66000 r-xp 00000000 08:01 1041511 /home/bob/lib/libgcc_s.so.1
f7e66000-f7e67000 rwxp 00009000 08:01 1041511 /home/bob/lib/libgcc_s.so.1
f7e67000-f7e68000 rwxp 00000000 00:00 0
f7e68000-f7e8c000 r-xp 00000000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8c000-f7e8d000 r-xp 00023000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8d000-f7e8e000 rwxp 00024000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8e000-f7f3d000 r-xp 00000000 08:01 1041514 /home/bob/lib/libstdc++.so.5
f7f3d000-f7f42000 rwxp 000ae000 08:01 1041514 /home/bob/lib/libstdc++.so.5
f7f42000-f7f47000 rwxp 00000000 00:00 0
f7f47000-f7f56000 r-xp 00000000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f56000-f7f57000 r-xp 0000e000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f57000-f7f58000 rwxp 0000f000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f58000-f7f9b000 rwxp 00000000 00:00 0
f7f9b000-f7f9e000 r--p 00000000 00:00 0 [vvar]
f7f9e000-f7f9f000 r-xp 00000000 00:00 0 [vdso]
f7f9f000-f7fb8000 r-xp 00000000 08:01 1041509 /home/bob/lib/ld-linux.so.2
f7fb8000-f7fb9000 r-xp 00018000 08:01 1041509 /home/bob/lib/ld-linux.so.2
f7fb9000-f7fba000 rwxp 00019000 08:01 1041509 /home/bob/lib/ld-linux.so.2
ff000000-ff001000 ---p 00000000 00:00 0
ff001000-ff200000 rwxp 00000000 00:00 0
ff200000-ff201000 ---p 00000000 00:00 0
ff201000-ff400000 rwxp 00000000 00:00 0
ff400000-ff401000 ---p 00000000 00:00 0
ff401000-ff600000 rwxp 00000000 00:00 0
ff600000-ff601000 ---p 00000000 00:00 0
ff601000-ff800000 rwxp 00000000 00:00 0
fff4b000-fffa2000 rwxp 00000000 00:00 0 [stack]
My server spawns each thread as an independent process, and as you can see I had to use my libraries (/home/bob/lib) copied from and ancient RedHat version which was compatible with the threading model (getpid() returns a different value for each thread).
I would really like to hear some suggestions on how I can inject new code. Is it just as hacky as writing directly to /proc/pid/mem? How would I override a game function (say, HandlePlayerMove) with /proc/pid/mem? Is it possible to inject a shared object using LD_PRELOAD given that it was compiled against a newer version of libc, libm, etc? Is there a way of knowing what's triggering SIGSEGV without ptrace failing?
edit: dummy code typo

mmap error : segmentation fault/invalid pointer error

I am new to mmap and still learning it . Based on my understanding i have created class for mmap which will be used to map a file in memory . The entire class is working fine but problem is coming when destructor is called ..the problem is segmentation fault or invalid pointer error is coming at the end of main function ...I have posted code of my class and main function which is using that class ...
Map.h
class MapData
{
public :
MapData();
~MapData();
MapData(char []);
bool OPEN();
void fnClose();
long fnGetSize();
char * fnGetFileRef();
char * ReadNextData(int );
private :
char * ptrRecord;
char ptrFileNm[250+1];
int fd;
struct stat sbuf;
bool bSuccess;
long sTotalSize;
char acData[2000+1];
long lCurrRead;
};
MapData.cpp
MapData::MapData()
{
}
MapData::~MapData()
{
printf("Inside MADATA Destructor \n ");
}
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}
bool MapData::OPEN()
{
// if failed return false flg
if ((fd = open(ptrFileNm, O_RDONLY)) == -1) {
return bSuccess;
}
if (stat(ptrFileNm, &sbuf) == -1) {
return bSuccess;
}
// copy in local variable
sTotalSize = sbuf.st_size;
ptrRecord = (char * )mmap( (caddr_t)0, sTotalSize, PROT_READ, MAP_SHARED, fd, 0) ;
if (ptrRecord == (char *)(caddr_t)(-1) ) {
perror("Fail to Map Data ");
return bSuccess;
}
else
{
printf("Successfully Map Data***[%ld] \n",sTotalSize);
bSuccess=true;
}
return bSuccess;
}
char * MapData::fnGetFileRef()
{
return ptrRecord;
}
char * MapData::ReadNextData(int iX)
{
if((lCurrRead+iX)<sTotalSize)
{
memset(acData,0x00,sizeof(acData));
strncpy(acData,ptrRecord+lCurrRead,iX);
acData[iX+1]='\0';
lCurrRead+=iX;
}else{
strcpy(acData,"ZZZ");
}
return acData;
}
long MapData::fnGetSize()
{
return sTotalSize;
}
void MapData::fnClose()
{
// Don't forget to free the mmapped memory
if(munmap(ptrRecord, sTotalSize) == -1)
{
close(fd);
perror("Error un-mmapping the file");
exit(EXIT_FAILURE);
}
// Un-mmaping doesn't close the file, so we still need to do that.
close(fd);
printf("CLOSED SUCCESSFULLY \n ");
}
Main.cpp
int main()
{
char acFileNm[500+1];
MEMSET(acFileNm); // clean the variable
// file name to be read
strcpy(acFileNm,"ABDFILE.txt");
long lProcCnt=0; // no of byte read by program
char acLine[MAX_LINE_LENGTH+1]; // hold current read line
bool bFlag=true; // main flag
DEBUG_PRINT("File to be processed:%s \n",acFileNm);
// create object of mmap
MapData * pt1 = NULL;
pt1 = new MapData(acFileNm);
if(!pt1)
{
cout<<"Error creating object so quit ..."<<endl;
return 0 ;
}
auto_ptr<MapData> ptrMap( pt1 ); // pass ownership to auto deletor to delete memory
DEBUG_PRINT("STEP1:%s \n","OBJECT CREATION FOR FILE MAPPED IN MEMORY");
// try to open the file
if(ptrMap->OPEN())
{
// on success..get pointer to first char of file
char * ptrData = ptrMap->fnGetFileRef();
long lCompSize=ptrMap->fnGetSize(); // total no of bytes = fiexed line size * no of row + (no of row * EOL)
short int iEOL=0;
// logic to identify file generated on ewhich OS
if( (*(ptrData+MAX_LINE_LENGTH) == '\r') && (*(ptrData+MAX_LINE_LENGTH+1) == '\n'))
{
// DOS format CRLF
iEOL = 2;
}else if(*(ptrData+MAX_LINE_LENGTH) == '\n'){
// Unix format LF
iEOL = 1;
}
DEBUG_PRINT("STEP2: SIZEOFFILE%ld FILESYSTEM FORMAT:%d \n",lCompSize,iEOL);
// here read till it reaches maximum limit of file
while(lProcCnt<lCompSize)
{
//DEBUG_PRINT("PROC COUNTER[%ld] MAX_COUNTER[%ld] \n",lProcCnt,lCompSize);
lProcCnt+=MAX_LINE_LENGTH+iEOL; // increement no of bytes read at initial
MEMSET(acLine);
strncpy(acLine,ptrData+lProcCnt,MAX_LINE_LENGTH); // read line
acLine[MAX_LINE_LENGTH+1]='\0';
// process the line :function is called here to process the line
}
}else{
DEBUG_PRINT("MAP DATA FAILED OF FILE[%s] \n",acFileNm);
bFlag=false;
}
// at the end check if all the controls are matched
if(bFlag)
DEBUG_PRINT("END OF FILE PROCESSING SUCCESS \n");
else
DEBUG_PRINT("END OF FILE PROCESSING FAILED \n");
// close the memory map
ptrMap->fnClose();
MapData * ptr5 = ptrMap.release(); // release the ownership
delete ptr5; **// segmentation fault comes here ...**
}
Please suggest me where i am going wrong since gdb is also not helping ...detailed explanation will be good for me to understand ...
Stacktrace generated by gdb:
*** glibc detected *** DemoMap: free(): invalid pointer: 0x0804c000 ***
======= Backtrace: =========
/lib/libc.so.6[0x9bbc81]
/lib/libc.so.6[0x9be562]
/usr/lib/libstdc++.so.6(_ZdlPv+0x22)[0x544552]
DemoMap[0x80491e6]
/lib/libc.so.6(__libc_start_main+0xe6)[0x961d36]
DemoMap[0x8048d91]
======= Memory map: ========
00110000-00111000 r-xp 00000000 00:00 0 [vdso]
0044c000-00469000 r-xp 00000000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00469000-0046a000 rw-p 0001d000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00495000-00576000 r-xp 00000000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
00576000-0057a000 r--p 000e0000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057a000-0057c000 rw-p 000e4000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057c000-00582000 rw-p 00000000 00:00 0
00929000-00947000 r-xp 00000000 08:03 1065 /lib/ld-2.12.so
00947000-00948000 r--p 0001d000 08:03 1065 /lib/ld-2.12.so
00948000-00949000 rw-p 0001e000 08:03 1065 /lib/ld-2.12.so
0094b000-00adb000 r-xp 00000000 08:03 1067 /lib/libc-2.12.so
00adb000-00adc000 ---p 00190000 08:03 1067 /lib/libc-2.12.so
00adc000-00ade000 r--p 00190000 08:03 1067 /lib/libc-2.12.so
00ade000-00adf000 rw-p 00192000 08:03 1067 /lib/libc-2.12.so
00adf000-00ae2000 rw-p 00000000 00:00 0
00b29000-00b51000 r-xp 00000000 08:03 1211 /lib/libm-2.12.so
00b51000-00b52000 r--p 00027000 08:03 1211 /lib/libm-2.12.so
00b52000-00b53000 rw-p 00028000 08:03 1211 /lib/libm-2.12.so
08048000-0804b000 r-xp 00000000 08:08 2883976 DemoMap
0804b000-0804c000 rw-p 00002000 08:08 2883976 DemoMap
0804c000-0806d000 rw-p 00000000 00:00 0 [heap]
b7e00000-b7e21000 rw-p 00000000 00:00 0
b7e21000-b7f00000 ---p 00000000 00:00 0
b7f9b000-b7fe5000 r--s 00000000 08:08 4326707 ABCDEF.TXT
b7fe5000-b7fe8000 rw-p 00000000 00:00 0
b7ffd000-b8000000 rw-p 00000000 00:00 0
bffeb000-c0000000 rw-p 00000000 00:00 0 [stack]
may be here.
char ptrFileNm[250+1];
char acFileNm[500+1];
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);//segmentation fault
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}

Error in `main': free(): invalid pointer (though no free or delete used)

I have this simple code that i m trying to run in tutorialspoint.com
#include <iostream>
using namespace std;
class Vehicle {
string vehicleNo;
string color;
protected:
string getVehicleNo()
{
return vehicleNo;
}
string setVehicleNo(string num)
{
vehicleNo = num;
}
string getColor()
{
return color;
}
string setColor(string someColor)
{
color = someColor;
}
};
class Car: public Vehicle {
private:
int distance;
public:
void setDistance(int a)
{
distance = a;
}
int calculateFare(int)
{
return distance * 5;
}
void displayInformation()
{
cout << distance << endl;
}
void useSetVehicleNo(string num)
{
setVehicleNo(num);
}
string useSetColor(string someColor)
{
setColor(someColor);
}
string useGetVehicleNo()
{
return getVehicleNo();
}
string useGetColor()
{
return getColor();
}
};
int main()
{
//string exit=n;
string vehicleNo;
string color;
Car car;
cout << "Enter car number : " << endl;
cin >> vehicleNo;
car.useSetVehicleNo(vehicleNo);
cout << "Enter car color : " << endl;
cin >> color;
car.useSetColor(color);
//vehicleNo = car.useGetColor();
//color = car.useGetVehicleNo();
//cout << vehicleNo;
//cout << color;
return 0;
}
Running this is giving me the following output
Enter car number :
1
Enter car color :
g
* Error in `main': free(): invalid pointer: 0x00007ff3aa205ba8 *
======= Backtrace: ========= /lib64/libc.so.6(+0x7850e)[0x7ff3a969450e]
/lib64/libc.so.6(cfree+0x5b5)[0x7ff3a96a0165]
main[0x400e97]
main[0x400c79]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7ff3a963bfe0]
main[0x400ac9]
======= Memory map: ======== 00400000-00402000 r-xp 00000000 fd:11f 59330668
/home/cg/roo t/main
00601000-00602000 r--p 00001000 fd:11f 59330668
/home/cg/roo t/main
00602000-00603000 rw-p 00002000 fd:11f 59330668
/home/cg/roo t/main
0140c000-0142d000 rw-p 00000000 00:00 0
[heap]
7ff3a961c000-7ff3a97d0000 r-xp 00000000 fd:11f 37749826
/usr/lib64/l
ibc-2.20.so
7ff3a97d0000-7ff3a99cf000 ---p 001b4000 fd:11f 37749826
/usr/lib64/l
ibc-2.20.so
7ff3a99cf000-7ff3a99d3000 r--p 001b3000 fd:11f 37749826
/usr/lib64/l
ibc-2.20.so
7ff3a99d3000-7ff3a99d5000 rw-p 001b7000 fd:11f 37749826
/usr/lib64/l
ibc-2.20.so
7ff3a99d5000-7ff3a99d9000 rw-p 00000000 00:00 0
7ff3a99d9000-7ff3a99ef000 r-xp 00000000 fd:11f 37749844
/usr/lib64/l
ibgcc_s-4.9.2-20141101.so.1 7ff3a99ef000-7ff3a9bee000 ---p
00016000 fd:11f 37749844 /usr/lib64/l
ibgcc_s-4.9.2-20141101.so.1
7ff3a9bee000-7ff3a9bef000 r--p 00015000 fd:11f 37749844
/usr/lib64/l
ibgcc_s-4.9.2-20141101.so.1
7ff3a9bef000-7ff3a9bf0000 rw-p 00016000 fd:11f 37749844
/usr/lib64/l
ibgcc_s-4.9.2-20141101.so.1
7ff3a9bf0000-7ff3a9cf7000 r-xp 00000000 fd:11f 37749280
/usr/lib64/l
ibm-2.20.so
7ff3a9cf7000-7ff3a9ef6000 ---p 00107000 fd:11f 37749280
/usr/lib64/l
ibm-2.20.so
7ff3a9ef6000-7ff3a9ef7000 r--p 00106000 fd:11f 37749280
/usr/lib64/l
ibm-2.20.so
7ff3a9ef7000-7ff3a9ef8000 rw-p 00107000 fd:11f 37749280
/usr/lib64/l
ibm-2.20.so
7ff3a9ef8000-7ff3a9fe8000 r-xp 00000000 fd:11f 37749829
/usr/lib64/l
ibstdc++.so.6.0.20
7ff3a9fe8000-7ff3aa1e8000 ---p 000f0000 fd:11f 37749829
/usr/lib64/l
ibstdc++.so.6.0.20
7ff3aa1e8000-7ff3aa1f0000 r--p 000f0000 fd:11f 37749829
/usr/lib64/l
ibstdc++.so.6.0.20
7ff3aa1f0000-7ff3aa1f2000 rw-p 000f8000 fd:11f 37749829
/usr/lib64/l
ibstdc++.so.6.0.20
7ff3aa1f2000-7ff3aa207000 rw-p 00000000 00:00 0
7ff3aa207000-7ff3aa228000 r-xp 00000000 fd:11f 37856921
/usr/lib64/l d-2.20.so
7ff3aa412000-7ff3aa417000 rw-p 00000000 00:00 0
7ff3aa424000-7ff3aa428000 rw-p 00000000 00:00 0
7ff3aa428000-7ff3aa429000 r--p 00021000 fd:11f 37856921
/usr/lib64/l d-2.20.so
7ff3aa429000-7ff3aa42a000 rw-p 00022000 fd:11f 37856921
/usr/lib64/l 7ff3aa429000-7ff3aa42a000 rw-p 00022000 fd:11f
37856921 /usr/lib64/l
d-2.20.so
7ff3aa42a000-7ff3aa42b000 rw-p 00000000 00:00 0
7fff1dddb000-7fff1ddfc000 rw-p 00000000 00:00 0
[stack]
7fff1ddfe000-7fff1de00000 r-xp 00000000 00:00 0
[vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0
[vsyscall] Aborted
(core dumped)
You have three functions that have a return type different than void where you don't have a valid return statement.
If you turn your warning level up, your compiler will tell you about them. When using g++ -Wall, I get the following messages:
socc.cc: In member function ‘std::string Vehicle::setVehicleNo(std::string)’:
socc.cc:19:4: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
socc.cc: In member function ‘std::string Vehicle::setColor(std::string)’:
socc.cc:29:4: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
socc.cc: In member function ‘std::string Car::useSetColor(std::string)’:
socc.cc:60:7: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
Calling such functions leads to undefined behavior.
From the C++11 Standard:
6.6.3 return statement
2 ...
...
Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
You can fix the problem by adding a suitable return statement. E.g.
The first function:
string setVehicleNo(string num)
{
vehicleNo = num;
return vehicleNo; // Add this, maybe?
}
The second function:
string setColor(string someColor)
{
color = someColor;
return color; // Add this, maybe
}
The third function:
string useSetColor(string someColor)
{
return setColor(someColor); // Add the return, maybe?
}
Your problems are here:
string setVehicleNo(string num)
// ^^^^^^
{
vehicleNo = num;
}
You are defining a return type but don't return a value actually (you should have gotten a compiler warning about this).
To fix either specify a void return type, or return a value.
Analogous for your other functions. See a fixed demo here.
Do the following changes in your code :
first -
string setVehicleNo(string num)
// ^^^^^^
{
vehicleNo = num;
}
second -
string setColor(string someColor)
// ^^^^^^
{
color = someColor;
}
third -
string useSetColor(string someColor)
//^^^^^^
{
setColor(someColor);
}
You have assign return type to string but not returning any value. changed it to void. see the changes made here http://ideone.com/n1Wg15

Glibc Error: double free or corruption

I have been looking around at the meaning of this error and it seems to mean that I am freeing the same object more than once. I can't seem to figure out how to prevent this. Any help or suggestions would be much appreciated.
File(randname)
File(a.out)
~File(a.out)
~Directory(randname)
~File(null)
~File()
*** glibc detected *** a.out: double free or corruption (fasttop): 0x0804b048 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6ff0b)[0xb74baf0b]
/usr/local/gcc/gcc-cilk/lib/libstdc++.so.6(_ZdlPv+0x1f)[0xb7671b4f]
/usr/local/gcc/gcc-cilk/lib/libstdc++.so.6(_ZdaPv+0x1b)[0xb7671b9b]
a.out[0x8048983]
a.out[0x8048b12]
a.out[0x80487d7]
/lib/libc.so.6(__libc_start_main+0xf3)[0xb7464003]
a.out[0x8048701]
======= Memory map: ========
08048000-08049000 r-xp 00000000 00:25 268562602 /home/user/test/a.out
08049000-0804a000 r--p 00000000 00:25 268562602 /home/user/test/a.out
0804a000-0804b000 rw-p 00001000 00:25 268562602 /home/user/test/a.out
0804b000-0806c000 rw-p 00000000 00:00 0 [heap]
b7448000-b744b000 rw-p 00000000 00:00 0
b744b000-b75b2000 r-xp 00000000 08:01 1365267 /lib/libc-2.14.1.so
b75b2000-b75b4000 r--p 00167000 08:01 1365267 /lib/libc-2.14.1.so
b75b4000-b75b5000 rw-p 00169000 08:01 1365267 /lib/libc-2.14.1.so
b75b5000-b75b8000 rw-p 00000000 00:00 0
b75b8000-b75d3000 r-xp 00000000 08:01 1179017 /usr/local/gcc/gcc-cilk/lib/libgcc_s.so.1
b75d3000-b75d4000 r--p 0001a000 08:01 1179017 /usr/local/gcc/gcc-cilk/lib/libgcc_s.so.1
b75d4000-b75d5000 rw-p 0001b000 08:01 1179017 /usr/local/gcc/gcc-cilk/lib/libgcc_s.so.1
b75d5000-b75fe000 r-xp 00000000 08:01 1365275 /lib/libm-2.14.1.so
b75fe000-b75ff000 r--p 00028000 08:01 1365275 /lib/libm-2.14.1.so
b75ff000-b7600000 rw-p 00029000 08:01 1365275 /lib/libm-2.14.1.so
b7622000-b7624000 rw-p 00000000 00:00 0
b7624000-b770b000 r-xp 00000000 08:01 1179021 /usr/local/gcc/gcc-cilk/lib/libstdc++.so.6.0.19
b770b000-b770f000 r--p 000e7000 08:01 1179021 /usr/local/gcc/gcc-cilk/lib/libstdc++.so.6.0.19
b770f000-b7710000 rw-p 000eb000 08:01 1179021 /usr/local/gcc/gcc-cilk/lib/libstdc++.so.6.0.19
b7710000-b7718000 rw-p 00000000 00:00 0
b7718000-b7737000 r-xp 00000000 08:01 1365260 /lib/ld-2.14.1.so
b7737000-b7738000 r--p 0001f000 08:01 1365260 /lib/ld-2.14.1.so
b7738000-b7739000 rw-p 00020000 08:01 1365260 /lib/ld-2.14.1.so
bfa18000-bfa39000 rw-p 00000000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Aborted
And here is the code:
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
class File
{
protected:
unsigned char recordLen;
unsigned location;
unsigned fileSize;
unsigned char filenameLen;
char* filename;
public:
File(){filename = NULL;}
File(FILE* readFromHere, const char* name)
{
recordLen = 152;
location = 20003;
fileSize = 16348;
filenameLen = strlen(name);
filename = new char[filenameLen + 1];
strcpy(filename, name);
cout << "File(" << filename << ")\n";
}
File(const File& o)
{
if (o.filename == NULL)
filename = o.filename;
else
{
filename = new char[o.filenameLen + 1];
strcpy(filename, o.filename);
}
}
~File()
{
if (filename)
cout << "~File(" << filename << ")\n";
else
cout << "~File(null)\n";
if (filename != NULL)
delete[] filename;
}
};
class Directory : public File
{
protected:
int numContents;
File* contents;
public:
Directory(FILE* readFromHere, const char* name)
: File(readFromHere, name)
{
numContents = 2;
contents = new File[numContents];
contents[0] = File(readFromHere, "a.out");
//~ contents[1] = File(readFromHere, "otherfile.cpp");
}
~Directory()
{
if (filename)
cout << "~Directory(" << filename << ")\n";
else
cout << "~Directory(null)\n";
if (contents != NULL)
delete[] contents;
}
};
int main()
{
Directory d(NULL, "randname");
sleep(2);
return 0;
}
Your class doesn't follow the Rule of Three even though it owns resources. You have a copy constructor and a destructor, but not a copy assignment operator. Which means that this line:
contents[0] = File(readFromHere, "a.out");
invokes the default copy assignment operator, which happily copies pointers. There's your double-deletion problem.

Stack Smashing Using Message Queues

i have the following main code:
#include "ComHandler.h"
#include "socketMessage.h"
#define THIS_IP "localhost"
#define C_PORT 32456
#define S_PORT 25465
#define S_PORT_UDP 22548
int main(int argc, char* argv[]) {
conOptions opts;
strncpy(opts.password, "PASS", sizeof("PASS"));
opts.retryQty = 5;
opts.timeout = 300;
char dir[INET6_ADDRSTRLEN];
strncpy(dir, THIS_IP, sizeof(THIS_IP));
if (argv[1][0] == 'C') {
opts.connType = CLIENT_HANDLER;
opts.thisID = 2;
ComHandler comH(opts);
char buffer[10];
strncpy(buffer, "Testing", 10);
int rtnValue = comH.sendMsg(buffer, 10, 1, TCP_C);
std::cout << "Returned Value: " << rtnValue << std::endl;
} else {
opts.connType = SERVER_HANDLER;
opts.thisID = 1;
ComHandler comH(opts);
comH.addConnectionData(2, dir, C_PORT);
comH.addConnectionData(comH.getID(), dir, S_PORT);
char rcvdTxt[MINIDATA_DATA_SIZE];
comH.receiveMsg(rcvdTxt, MINIDATA_DATA_SIZE, 2, TCP_C);
std::cout << "Received: " << rcvdTxt << std::endl;
comH.closeCommunications();
}
}
The code is for testing my communication platform. The platform works well, but the problem appears when the messages are received by the Handler (ComHandler). When i call the method "receiveMsg" from ComHandler, i get a "stack smashing detected" in the "return" of the method.
This is the "ComHandler" class:
#ifndef COMHANDLER_H_
#define COMHANDLER_H_
#include "Constants.h"
#include "ComConstants.h"
#include "DataLogger.h"
#include <list>
#include <math.h>
#define CLIENT_HANDLER 1
#define SERVER_HANDLER 2
#define COMMENT_LINE '#'
#define TXT_SEPARATOR ';'
#define MINIDATA_DATA_SIZE (COMDATA_MAX_SIZE - 4* sizeof(int))
enum CON_TYPE {
TCP_C, UDP_C
};
#pragma pack(push)
#pragma pack(1)
typedef struct {
int totalPackets;
int sequenceNumber;
int sequenceID;
int dataSize;
char data[MINIDATA_DATA_SIZE];
} miniData;
#pragma pack(pop)
typedef struct connectionOptions {
unsigned int timeout;
unsigned int retryQty;
id_t thisID;
char password[PASSWORD_MAX_SIZE];
int connType;
connectionOptions() :
timeout(CON_TIMEOUT), retryQty(SOCKET_RETRIES), connType(
SERVER_HANDLER) {
memset(password, 0, PASSWORD_MAX_SIZE);
}
connectionOptions(connectionOptions& opt) {
timeout = opt.timeout;
retryQty = opt.retryQty;
thisID = opt.thisID;
connType = opt.connType;
memcpy(password, opt.password, PASSWORD_MAX_SIZE);
}
} conOptions;
class ComHandler {
private:
int dataForwarder_ReceiverMsgQueue;
int dataForwarder_SenderMsgQueue;
conOptions opts;
int sequenceID;
Semaphore ch_mux;
SharedMemory<comHandlerGlOp> ch_shm;
void cpyMiniData(miniData* to, miniData* from);
void createIPCs();
public:
ComHandler();
ComHandler(conOptions options);
ComHandler(id_t thisID);
virtual ~ComHandler();
int receiveMsg(char* buffer, int bufferSize, id_t originID,
CON_TYPE type = TCP_C);
int sendMsg(char* buffer, std::size_t bufferSize, id_t destinationID,
CON_TYPE type = TCP_C);
void configListenersData(char addr[INET6_ADDRSTRLEN], int port,
CON_TYPE type);
void addConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port);
void addConnectionData(const char* file);
void modifyConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port);
void removeConnectionData(id_t id);
int getID();
void closeCommunications();
};
#endif /* COMHANDLER_H_ */
The comData structure:
typedef struct {
long type;
int requestType;
char destination[INET6_ADDRSTRLEN];
char origin[INET6_ADDRSTRLEN];
id_t originID;
id_t destinationID;
int port;
pid_t senderPid;
pid_t originPid;
char data[COMDATA_MAX_SIZE];
} comData;
And the method with the problem:
int ComHandler::receiveMsg(char* buffer, int bufferSize, id_t originID,
CON_TYPE type) {
comData aux;
aux.type = DATA_RECEIVE;
int qtyReceived = 0;
if (originID != ANY_MSG_ORIGIN) {
if (type == TCP_C)
aux.requestType = RECEIVE_DATA_FROM_DESTINATION_TCP;
else
aux.requestType = RECEIVE_DATA_FROM_DESTINATION_UDP;
} else {
if (type == TCP_C)
aux.requestType = RECEIVE_ANY_DATA_TCP;
else
aux.requestType = RECEIVE_ANY_DATA_UDP;
}
aux.originID = originID;
aux.senderPid = getpid();
aux.originPid = getpid();
msgsnd(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), 0);
msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0);
/* More Code */
return qtyReceived;
}
The stack smashing error appears after "return qtyReceived;" is called. And the /* More Code */ in the middle is the non important code, because if a delete that part, the stack smashing stills appears.
After much debugging i found that the smashing appears if i call:
`msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0);`
if i comment that line, i don't get the error.
Also with the debugger, i was able to see that the messages from the queue arrive with good format and size, exactly as they should.
The console output is:
*** stack smashing detected ***: /media/blackhole/workspace/Final/bin/ComTest terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7df88d5]
/lib/i386-linux-gnu/libc.so.6(+0xe7887)[0xb7df8887]
/media/blackhole/workspace/Final/bin/ComTest[0x804dc6b]
/media/blackhole/workspace/Final/bin/ComTest[0x804a002]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7d2a113]
/media/blackhole/workspace/Final/bin/ComTest[0x8049d11]
======= Memory map: ========
08048000-08054000 r-xp 00000000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08054000-08055000 r--p 0000b000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08055000-08056000 rw-p 0000c000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08056000-08077000 rw-p 00000000 00:00 0 [heap]
b7d0f000-b7d11000 rw-p 00000000 00:00 0
b7d11000-b7e87000 r-xp 00000000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e87000-b7e89000 r--p 00176000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e89000-b7e8a000 rw-p 00178000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e8a000-b7e8d000 rw-p 00000000 00:00 0
b7e8d000-b7ea9000 r-xp 00000000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7ea9000-b7eaa000 r--p 0001b000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7eaa000-b7eab000 rw-p 0001c000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7eab000-b7eac000 rw-p 00000000 00:00 0
b7eac000-b7ed4000 r-xp 00000000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed4000-b7ed5000 r--p 00028000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed5000-b7ed6000 rw-p 00029000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed6000-b7fb4000 r-xp 00000000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb4000-b7fb5000 ---p 000de000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb5000-b7fb9000 r--p 000de000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb9000-b7fba000 rw-p 000e2000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fba000-b7fc1000 rw-p 00000000 00:00 0
b7fdc000-b7fdd000 rw-s 00000000 00:04 163119127 /SYSV02056f32 (deleted)
b7fdd000-b7fdf000 rw-p 00000000 00:00 0
b7fdf000-b7fe0000 r-xp 00000000 00:00 0 [vdso]
b7fe0000-b7ffe000 r-xp 00000000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
b7ffe000-b7fff000 r--p 0001d000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
b7fff000-b8000000 rw-p 0001e000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
bffdf000-c0000000 rw-p 00000000 00:00 0 [stack]
So, any ideas? If you need something about the code, just ask me.
According to this, the msgsz parameter of msgrcv() should be the size of the mtext member of the mymsg struct:
struct mymsg {
long int mtype; /* message type */
char mtext[1]; /* message text */
}
The problem is that you include the size of the mtype member (4 bytes) so msgrcv() writes four bytes past the end of your struct which trashes the stack.