Last active
April 29, 2016 23:50
-
-
Save datenwolf/faf828e9facb53929482a94220441a15 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <malloc.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <sys/prctl.h> | |
/* this is a borken function that exhibits undefined behavior. | |
* in likely circumstances it will cause the process to crash... | |
* ... eventually (if it crashes at all) | |
*/ | |
void crasher(char *p, unsigned i) | |
{ | |
p[0] = '\n'; | |
memset(p + 1, '.', i + 1); | |
strcpy(p + i, "crash"); | |
} | |
int forked_crasher(char *p, size_t sz_p, unsigned i) | |
{ | |
int status; | |
/* we somehow have to get the data back to the caller process */ | |
int r_read; | |
int fd_pipe[2]; | |
size_t p_read = 0; | |
if( pipe(fd_pipe) ) { return -1; } | |
/* by fork-ing a new, separate process that's a nearly identical | |
* clone, with all of the address space and its contents is | |
* created and starts running. Everything that happens in this | |
* process, stays in this process (just like Las Vegas) */ | |
pid_t const pid = fork(); | |
if( 0 > pid ) { | |
close(fd_pipe[0]); | |
close(fd_pipe[1]); | |
return -2; | |
} | |
if( !pid ) { | |
/* see pipe(2) for details on how to use a pipe and why we close | |
* the reading end here. Essentially we don't need it, and keeping | |
* the reading end open would cause trouble down the line. */ | |
close(fd_pipe[0]); | |
/* prevent process crashes to create dump file. if we expect a | |
* crash, then this is desireable, as we don't want to spam | |
* the working directory with core dump files. */ | |
prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); | |
/* calling the function that may crash */ | |
crasher(p, i); | |
/* it survived! Hooray \o/ ... now get the result back to parent */ | |
fprintf(stderr, "%u\n", i); | |
write(fd_pipe[1], p, sz_p); | |
close(fd_pipe[1]); | |
/* this process copy has done its deed. Terminate it */ | |
_exit(0); | |
} | |
/* close the writing end of the pipe in the parent process. */ | |
close(fd_pipe[1]); | |
/* read the result back from the child */ | |
do { | |
do { | |
r_read = read(fd_pipe[0], (p + p_read), (sz_p - p_read)); | |
} while( 0 > r_read && EAGAIN == errno ); | |
if( 0 < r_read ) { | |
p_read += r_read; | |
} | |
} while( 0 < r_read ); | |
if( 0 == r_read ) { | |
waitpid(pid, &status, 0); | |
if( WIFSIGNALED(status) ) { | |
fprintf(stderr, | |
"%u: forked crasher terminated with signal %d\n", | |
i, | |
(int)WTERMSIG(status) ); | |
} | |
} | |
close(fd_pipe[0]); | |
return 0; | |
} | |
void looper(void) | |
{ | |
unsigned i; | |
size_t const sz_mem = 0x1000; | |
char *mem = malloc(sz_mem); | |
if( !mem ) { return; } | |
for(i = 0; i < 0x40000; i += 0x100) | |
{ | |
memset(mem, 0, sz_mem); | |
forked_crasher(mem, sz_mem, i); | |
fwrite(mem, strlen(mem), 1, stdout); | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
looper(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment