Check out the new USENIX Web site. next up previous
Next: Implementation Up: Type-Assisted Dynamic Buffer Overflow Previous: Indirect overflow via pointer

Overview of Our Approach

Array bounds checking is a direct way to detect buffer overflows, but it is difficult to do because the type information (hence the size) of buffers are not available in binary files except as optional debugging information in the symbol table. To enable range checking on buffers at run time, introduce an intermediary step in the compilation that emits an additional data structure into the binary file. This data structure describes the types of automatic buffers and static buffers. These types are known at compile time, so our data structure is complete for describing automatic and static buffers (there are two exceptions in which size of an automatic buffer cannot be determined at compile time, which are discussed in Section  6.). For example, buffers in a struct variable are safe from each other as depicted in Figure 1.

Figure 1: A struct containing two string buffers and a function pointer.
\begin{figure}\centerline{\parbox{104pt}{
\begin{tabbing}
struct mybuf \{\\
\hs...
...oid (*fptr)();\\
\hspace*{1em}char buf2[32];\\
\};
\end{tabbing}}}\end{figure}

For dynamically allocated (heap) objects, we maintain a table that tracks those objects and their sizes. Range checking is then done by looking up those data structures at run time. We use those data structures to perform range checking of arguments to the vulnerable string functions in the C library.

Regardless of which of these types of attack is attempted, buffers have to be overflowed in some way for the attacks to succeed. Since our approach prevents buffers from being overflowed it is insensitive to which attack was chosen. To truly protect from all the possible buffer overflow attacks in the most efficient way, we need to identify all and only those vulnerable points in the program. However it cannot be done without extensive source code analysis. For the current implementation we protect only C library functions. We believe that it is useful as a stand-alone protection system and can be easily extended with compile time analysis to remove bounds checking on ``known-safe'' function calls.

Our data structure for describing buffers is similar to the type table in the Process Introspection Library [9], which describes data types of savable memory blocks in order to checkpoint and restart processes in a distributed, heterogeneous environment. The Process Introspection Library also deduces the type of a heap allocated memory block, a capability that we currently lack, but which can be similarly added.


next up previous
Next: Implementation Up: Type-Assisted Dynamic Buffer Overflow Previous: Indirect overflow via pointer