fuckitllvm
An experiment in improving program reliability
LLVM
Motivation
Modern day C/C++ programming is hard.
Motivation
Javascript and Python developers have advanced tooling at their disposal
Motivation
We want to make compiled binaries that refuse to give up.
Motivation
We want to make compiled binaries that refuse to give up.
Or at least look like they might still be working.
Architectural Overview
Fuckitllvm is made up of a series of passes which improve reliability and resiliency.
Architectural Overview
Fuckitllvm is made up of a series of passes which improve reliability and resiliency.
These passes implement those values into target programs.
Error Redirection and Mitigation
Programs have two primary/standard ways of inconveniencing the user when they encounter potential problems.
Error Redirection and Mitigation
Programs have two primary/standard ways of inconveniencing the user when they encounter potential problems.
Our Solution: Mitigate the risk of unintended consequences by employing advanced redirection techniques.
Error Redirection and Mitigation
Programs have two primary/standard ways of inconveniencing the user when they encounter potential problems.
Dynamic Program Correction
Programs are not perfect. Sometimes, there are unavoidable mistakes.
int i = 0x41414141; *(int *)i = 0x10; printf("I'm still alive!\n");
Dynamic Program Correction
Programs are not perfect. Sometimes, there are unavoidable mistakes.
Advanced Program Analysis Techniques allow us to dynamically correct such subtle errors.
int i = 0x41414141; *(int *)i = 0x10; printf("I'm still alive!\n");
Dynamic Program Correction
Programs are not perfect. Sometimes, there are unavoidable mistakes.
int i = 0x41414141; *(int *)i = 0x10; printf("I'm still alive!\n");
Survival of the Fittest
Unfortunately, our program has to share resources with all other userspace programs.
Survival of the Fittest
Unfortunately, our program has to share resources with all other userspace programs.
Normal programs are prone to being terminated by other programs, especially if another program thinks it is malfunctioning.
Survival of the Fittest
Unfortunately, our program has to share resources with all other userspace programs.
Our Solution: Create a genetically superior program.
if ( (siginfo->si_signo == SIGTERM) ) {
if ( (my_pid != siginfo->si_pid)) {
// wanna fite m8?
kill(siginfo->si_pid, SIGKILL);
return;
}
}
Control Flow Recovery
Sometimes, things go really bad.
Like, end up at a point where something is calling SIGABRT bad.
Control Flow Recovery
Just catch it and try to find a suitable place to resume execution!
General Strategy:
Control Flow Recovery
Just catch it and try to find a suitable place to resume execution!
Problems:
Control Flow Recovery
Lots of pointers to places we don’t want to return to
Control Flow Recovery
Return there and throw the stack back around that spot.
Accidentally discovered an interesting problem!
Stack Frames for library calls are often somewhat “non-standard”.
Control Flow Recovery
Return there and throw the stack back around that spot.
Accidentally discovered an interesting problem!
Stack Frames for library calls are often somewhat “non-standard”.
Makes it difficult to “put the stack back”, so it matches the frame we return to.
Future Work
Add hooks before calling functions to record frame boundaries in some dedicated memory region.
Check if potential base pointers fall within these boundaries
Add try-catch around every basic block
Questions/Outrage?