CaVer is a runtime bad-casting detection tool. With the help of the LLVM compiler suite, CaVer first performs program instrumentations at compile time and then validates type casting based on a new runtime type tracing mechanism.
For more details and demos, please check our project page, ESHard. and the published paper Type Casting Verification: Stopping an Emerging Attack Vector, USENIX Security 2015.
CaVer won the Internet Defense Prize from Facebook and USENIX Security, and we are grateful for their supports.
make caver
This command creates the build directory build
. For example, clang
binary can be located from build/bin/clang-3.5
.
make test
This runs two different sets of testing, check-clang-cver
and check-cver
.
check-clang-cver
tests the correctness of Clang level code
generations including THTable emits and stack variable allocation
tracing. The testing code can be found in
llvm/tools/clang/test/CodeGen/cver
.
check-cver
does the end-to-end testing on the caver's bad-casting
detection capability. It includes various casting cases (e.g., from
(non-)polymorhpic classes to (non-)polymoprhic classes), and the
testing code can be found in
llvm/projects/compiler-rt/test/cver/TestCases
.
CaVer can be easily activated by adding one extra compiler flag,
-fsanitize=cver
. For example, suppose we want to protect the simple
bad-casting code, test.cc
(please check more bad-casting testcases
in compiler-rt to understand how CaVer handles more complicated
castings).
$ cat > test.cc
class S {};
class T : public S {
int m;
};
int main() {
S* ps = new S;
T* pt = static_cast<T*>(ps); // bad-casting!
return 0;
}
Assuming $BUILD_DIR points to the caver build directory,
test.cc
can be built using CaVer as follows.
$ $BUILD_DIR/bin/clang++ ./test.cc -o test -fsanitize=cver
Once executing the CaVer instrumented binary, test
, Caver generates
bad-casting reports at runtime including detailed informatoin on such
bad-casting and call stacks. Note, this call stack information can be
symbolized using llvm symbolizer.
$ ./test
== CastVerifier Bad-casting Reports
test.cc:8:11: Casting from 'S' to 'T'
Pointer 0x60200000f7d0
Alloc base 0x60200000f7d0
User base 0x60200000f7d0
Offset 0x000000000000
TypeTable 0x00000041e250
#0 0x402366 (/home/blee/project/cast_sanitizer/old_test/example/test+0x402366)
#1 0x41925a (/home/blee/project/cast_sanitizer/old_test/example/test+0x41925a)
#2 0x7ff496967ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#3 0x41912b (/home/blee/project/cast_sanitizer/old_test/example/test+0x41912b)
== End of reports.
The current version of CaVer made a direct changes to LLVM compiler suites, and it is branched out from
LLVM
: 9853f945205a0e1193afc3e84c10be96b4932d1bClang
: adc3bbec2b4d390277094b8f33df6ec25abe96b3Compiler-rt
: 23c70c8907fd669d4cbeeba59680e40fc1b61d19
, and applied a few upstream patches to fix regression bugs of LLVM compiler suites (which unfortunately mixed up with CaVer's changes).
In order to check the true changes that CaVer made to LLVM compiler suites, the best would be diffing from the branching point.
git diff 9b5950d61de7cade786239321298a874d7319a6d --stat
In a nutshell, CaVer's majors changes are as follows.
-
CGTHTables.h
inllvm/tools/clang/lib/CodeGen
implements Type Hierarchy Table. -
CGExpr.cpp
andCGExpr.cpp
inllvm/tools/clang/lib/CodeGen
inspects the casting operations, and instrument the runtime calls in case of downcasting. Much of the implementation is based on Undefined Sanitizers. -
CGDecl.cpp
inllvm/tools/clang/lib/CodeGen
instruments a tracing routine on stack variable allocation and deallocation. -
CastVerifier.cpp
inllvm/lib/Transforms/Instrumentation
implements a LLVM pass for CaVer. As an optimization technique, this pass enables CaVer to avoiding to trace unnecesary class allocations. -
cver_*.cc
andcver_*.h
inllvm/projects/compiler-rt/lib/cver
implements a runtime library of CaVer, which keeps track of allocation metadata and finally carries out casting verfication if required.