Preventing Buffer Overflows by Context-aware Failure-oblivious Computing

06/23/2018 ∙ by Manuel Rigger, et al. ∙ Johannes Kepler University Linz 0

In languages like C, buffer overflows are widespread. A common mitigation technique is to use tools that detect them during execution and abort the program to prevent the leakage of data or the diversion of control flow. However, for server applications, it would be desirable to prevent such errors while maintaining availability of the system. To this end, we present an approach to handle buffer overflows without aborting the program. This approach involves implementing a continuation logic in library functions based on an introspection function that allows querying the size of a buffer. We demonstrate that introspection can be implemented in popular bug-finding and bug-mitigation tools such as LLVM's AddressSanitizer, SoftBound, and Intel-MPX-based bounds checking. We evaluated our approach in a case study of real-world bugs and show that for tools that explicitly track bounds data, introspection results in a low performance overhead.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 1

page 2

page 3

page 4

This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

1 Introduction

Buffer overflows in C, where an out-of-bounds pointer is dereferenced, belong to the most dangerous software errors [5, 32]. Unlike higher-level languages, buffer overflows invoke Undefined Behavior and are not prevented during execution; programmers also cannot handle them using exception or similar mechanisms, since the language lacks them. Buffer overflows allow attackers to overflow function addresses stored on the stack or heap and thus to maliciously divert execution of the program [28] and to leak sensitive data [31]. A plethora of tools exist that make their exploitation more difficult or detect them and abort execution of the program [34, 32, 36, 30]. However, when availability of an application is important (e.g. for production servers), it would be preferable to continue execution as long as security is not compromised [24]. This could, for example, make it harder to perform a denial-of-service attack where a buffer overflow is exploited to crash the program or inject code.

To safely maintain execution in the presence of buffer overflows, we have come up with the concept of context-aware failure-oblivious computing. Our core idea is that library writers (e.g., the libc maintainers) can query run-time data such as bounds information in library functions by using an introspection interface. This information can then be used to implement a recovery logic that can mitigate incorrect execution states instead of aborting the program. Library writers can implement a custom recovery logic that depends on each function’s semantics, which is why we refer to our technique as being context-aware. For example, a libc function that processes an unterminated string could prevent an out-of-bounds access by checking for the end of the buffer to handle the fault and continue execution. We expect that this recovery logic would be used mainly in a production context, as it would be preferable that execution is aborted if an error occurs during development and testing so that programmers can fix the error.

Our work is based on a combination of failure-oblivious computing [25] and our previous work on an introspection interface for C to increase the robustness of libraries [23]. We show how the introspection interface can be used to implement a failure-oblivious computing mechanism. We evaluated our approach by demonstrating that introspection for preventing buffer overflows can be implemented in popular bug-finding and bug-mitigation tools such as LLVM’s AddressSanitizer [27], SoftBound [15], and GCC’s Pointer Bounds Checker, which is based on the Intel Memory Protection Extensions (MPX) [19]. Furthermore, we show how our approach allows execution to continue in the presence of buffer overflows found in real-world programs as described by the Common Vulnerabilities and Exposures (CVE) database [33], and demonstrate that the performance overhead for introspection implemented in approaches such as MPX is negligible.

2 Background

Failure-oblivious computing.

One technique for maintaining availability in the presence of buffer overflows is failure-oblivious computing, where invalid writes are discarded and values for invalid reads are manufactured [25, 26]. By carefully selecting a sequence of return values for invalid reads, the program can successfully continue execution in most cases. However, a drawback of this approach is that it is “blind”; that is, it cannot guess the context (i.e., a function’s semantics) to return a meaningful value for all reads. In this paper, we address this aspect by making failure-oblivious computing context-aware.

Introspection for C.

As part of previous work, we demonstrated how use of introspection (i.e., exposing run-time data) benefits the robustness of libraries [23]. The core idea of our approach was that bug-finding tools and runtimes for C that track additional metadata such as object bounds or object types can expose this data to library writers via an introspection interface, which programmers can use to check the input of library functions. We showed that various introspection functions can be used to detect bugs or to maintain availability of the program. For example, to detect buffer overflows by means of introspection, the _size_right() function can be applied, which expects a pointer and returns the number of allocated bytes to the right of the pointee (or zero for invalid pointers) and can therefore be used for bounds checks. In this paper, we expand on how introspection can be used to increase availability, which we define as context-aware failure-oblivious computing.

Evaluation of introspection.

We have previously evaluated an introspection libc using Safe Sulong [21, 22], an LLVM IR interpreter on top of the Java Virtual Machine (JVM) [20] which automatically keeps track of array lengths, object sizes, and object types of C data [23]. Although the JVM tracks all relevant run-time information necessary to implement our introspection mechanism, it is not a typical environment in which to execute C code. In this paper, we address this by evaluating our approach in the context of popular bug-finding and bug-mitigation tools for buffer overflows and show that our refined introspection approach prevents real-world errors while maintaining availability.

3 Introspection Interceptors

This section explains the implementation of the introspection-based libc functions. These enhanced functions rely on the _size_right() introspection function to mitigate buffer overflows. Challenges to introducing them were that the original code not be cluttered by the introspection checks, that the effort for implementing these checks be low, and that the code behave in the same way as the original library during correct execution.

Libc interceptors.

Based on our requirements, we implemented the introspection-based libc functions as interceptors, which are wrappers that intercept calls to libc functions and which are used by many bug-checking and bug-mitigation tools (including ASan, GCC’s Pointer Bounds Checker and SoftBound)111Note that in our previous work we instead reimplemented parts of a libc to use introspection, which made the libc less readable and required programs to be compatible with this libc.. The introspection logic was kept separate from the normal code to avoid cluttering of the original source code. The cost of adding introspection-based recovery logic was low, as for each unsafe function that we considered (e.g., strlen()), libc provides safer functions that expect an additional size argument, which we used for our implementation (e.g., strnlen()). By reusing existing libc functions from the same library, we expect correct execution to behave in the same way as without the interceptors. For example, consider our strlen() interceptor, which is based on the safer strnlen() function:

size_t strlen(const char *s) {
  return ORIGINAL(strnlen)(s, _size_right(s));
}

The ORIGINAL macro yields a reference to the function passed as its argument that is part of the library and prevents recursively calling interceptors. We implemented the _size_right() function in various memory-safety-checking tools, as described in Section 4. Both the original strlen() implementation and this interceptor behave correctly for strings that are terminated with a ‘\0’, which is needed to determine their length. However, if an unterminated string is passed to the original strlen() implementation, the function results in a buffer overflow that causes bug-finding and bug-mitigation tools to abort execution. Using the introspection-based interceptor instead prevents the buffer overflow, as the string length can be computed even for strings for which the ‘\0’ is missing, because the interceptor assumes the underlying buffer size to be the maximum length of the string. Note that application-level functions can still cause bug-finding and bug-mitigation tools to abort execution if these functions run over string bounds. However, in many cases, application-level functions process strings up to the length computed by strlen(), which consequently prevents an out-of-bounds access.

As another example, an introspection interceptor can address the insecure interface of gets(), which reads user input and writes it to a buffer whose size is unknown to the function:

char *gets(char *s) {
  return ORIGINAL(fgets)(s, _size_right(s), stdin);
}

Using introspection, gets() reads only as much user input as the buffer can store.

Some introspection interceptors correct invalid parameters, for instance, in memcpy:

void *memcpy(void *dest, const void *src,
             size_t n) {
  ssize_t dstsz = _size_right(dest);
  size_t len = n;
  if (dstsz < len) {
    len = dstsz;
  }
  return ORIGINAL(memcpy)(dest, src, len);
}

If the size of the destination buffer is smaller than the number of bytes that the function is expected to copy, the function ignores the writes that go out of bounds. Note that another check for the size of the source buffer would be applicable.

In contrast to our previous work [23], we treat the return value of _size_right()

as a conservative estimate of the object’s right bounds. This estimate can be the real size of the object, in which case the introspection interceptors work most reliably. However, it can also be at least as large as the actual allocation, which could include additional space due to alignment requirements (e.g., to accommodate approaches that track only allocation sizes). Finally, if no bounds information is available for a given pointer, returning

MAX_LONG effectively disables the introspection interceptors. This is useful, since it allows execution without recompilation of the code even when no tool is used that could determine the bounds of an object.

4 Introspection in Tools

We implemented _size_right() by exposing existing bounds information in three tools, namely LLVM’s AddressSanitizer [27], SoftBound [15], and GCC’s Intel MPX-based Pointer Bounds Checker instrumentation. SoftBound and LLVM’s AddressSanitizer (ASan) are both software-based approaches. SoftBound provides access to bounds information in constant time, and is therefore a favorable candidate for implementing introspection. ASan’s representation of metadata is suboptimal for implementing introspection, because it does not explicitly maintain bounds information and finding the end of an object takes linear time. By implementing introspection in ASan, we wanted to determine a worst-case overhead for implementing introspection in existing tools. Intel MPX instrumentation allowed us to additionally evaluate a hardware-based approach.

SoftBound.

SoftBound is a bounds checker that has also been enhanced by a mechanism (called CETS) to find temporal memory errors [16]. It tracks base and bounds information for every pointer as separate metadata. To propagate this metadata across call sites, SoftBound adds additional base and bounds metadata to pointer arguments of functions. To implement _size_right(), we return the right bounds of a pointee by subtracting its base address from its bounds, which are associated with the pointer. For all SoftBound experiments, we used the latest stable version 3.8.0, which is distributed together with CETS.

LLVM’s AddressSanitizer.

ASan is one of the most widely used bug-finding tools for C/C++ programs; it allows memory errors such as buffer overflows and use-after-free errors to be found by instrumenting the program during compile time. Its implementation is based on shadow memory [17], where a memory cell allocated by the program has a corresponding shadow memory cell that stores meta-information about the original allocation. To detect buffer overflows, ASan allocates space between allocations and marks the corresponding shadow memory as redzones; if a dereferenced pointer points to such a redzone, ASan detects the overflow and aborts the program. Shadow memory is not a favorable representation of metadata for introspection, since bounds information cannot be accessed in constant time. We implemented _size_right() in linear time by iterating over the current buffer until its associated shadow memory indicates that a redzone has been reached. For all LLVM and ASan experiments, we used the development branch of LLVM version 6.0.0 based on commit 1d871d6 in compiler-rt.

Intel MPX.

Intel MPX is an instruction set extension that adds instructions for creating, maintaining, and checking bounds information. Although its performance overhead is relatively high [19], providing buffer overflow protection at the hardware level is a promising research direction [35]. To use Intel MPX, we relied on GCC’s Pointer Bounds Checker instrumentation, which employs Intel MPX to verify bounds. Similarly to SoftBound’s implementation, we implemented _size_right() by querying the upper bounds (using a GCC builtin function) and subtracted the pointer address from it. For all experiments, we used GCC version 7.2.0.

Using libc.

To use our introspection-based libc extensions, we redefined the names of the libc functions by means of preprocessor macros. While this required recompilation of the target application, it allowed the tools to also instrument our introspection-based libc functions and did not require us to maintain bounds information, as libc calls from our interceptors invoked the tools’ interceptors. Note that our approach could be extended by using the dynamic loader to load the interceptors to retain binary compatibility (e.g., using the LD_PRELOAD mechanism); however, redefining the function names was less invasive.

5 CVE Case Study

To demonstrate the applicability of our approach in real-world projects, we considered recent (i.e., less than one year old) buffer overflows in widely-used software such as Dnsmasq, Libxml2, and GraphicsMagick. We selected the first libc-related bugs that we found in the CVE database for which an executable exploit existed. For each buffer overflow, we evaluated whether our introspection-based approach could mitigate the error and whether execution could successfully continue. Our approach prevented four out of five buffer overflows while successfully continuing execution; in one case, execution was aborted due to a subsequent buffer overflow in user-level code. Note that the unmodified tools also detected those buffer overflows; however, they aborted the program instead of mitigating the error and continuing execution. Since we performed this case study on complex real-world applications, and because SoftBound is a research prototype, we could not successfully execute any of these applications with it. The unmodified SoftBound version was also unable to execute them.222https://github.com/santoshn/softboundcets-3.8.0/issues/ However, we extracted the functions in which the errors occurred, which SoftBound could execute, and created a driver to trigger the bug.

Dnsmasq.

Dnsmasq is a lightweight DHCP server and caching DNS server which is used in many home routers.333http://www.thekelleys.org.uk/dnsmasq/doc.html In versions prior to 2.78, a bug existed that could cause a stack-based buffer overflow that allowed attackers to execute arbitrary code or to cause denial of service by crafting a DHCPv6 request with a wrong size (see CVE-2017-14493). It occurred in memcpy(), to which an incorrect size argument was passed:

state->mac_len = opt6_len(opt) - 2;
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);

A similar bug could be exploited for denial of service attacks (see CVE-2017-14496). It occurred in memset() and was triggered by an integer overflow:

/* Clear buffer beyond request to avoid risk of information disclosure. */
memset(((char *)header) + qlen, 0, (limit - ((char *)header)) - qlen);

When using our introspection interceptors, all tools continued execution by copying or setting up to as many bytes as the destination buffer could hold. The server stayed fully functional.

Libxml2.

Libxml2 is a widely used open-source XML parsing library.444http://xmlsoft.org/ For versions up to 2.9.4, a vulnerability in the xmlSnprintfElementContent() function enabled attackers to crash the application through a buffer overflow (see CVE-2017-9047). It was caused by an incorrect length validation (at another code location) followed by strcat():

if (content->name != NULL)
  strcat(buf, (char *) content->name);

The introspection interceptor for strcat() mitigated the buffer overflow by restricting the length of the concatenated string in all tools. The application continued execution and printed the truncated string as part of an error message. Although the error message was truncated, the output appeared reasonable from the user’s point of view.

GraphicsMagick.

GraphicsMagick is a widely used image processing tool.555http://www.graphicsmagick.org/ In version 1.3.26, its DescribeImage() function allowed attackers to overflow and corrupt the heap to execute arbitrary code or to cause denial-of-service attacks (see CVE-2017-16352). As shown below, the size argument in the call to strncpy() did not limit the number of copied bytes to the size of the buffer; instead, the number was calculated by the length of the directory name (which was determined by searching for the newline or NUL). Consequently, an overly long directory name could be used to cause an overflow:

for (p=image->directory; *p != ’\0’; p++) {
  q=p;
  while ((*q != ’\n’) && (*q != ’\0’))
    q++;
  (void) strncpy(image_info->filename,p,q-p);
  image_info->filename[q-p]=’\0’;
  p=q;
  // ...
}

The introspection interceptor for strncpy() successfully restricted the length of the copied string to the length of the destination buffer image_info->filename. However, in the line after the call to strncpy(), the program attempted to write a NUL character to the end of the string, which then caused an out-of-bounds access in the user application. The introspection approach does not protect against buffer overflows that happen in code that does not use introspection; however, we intend introspection to be used together with a bounds-checking tool, which is expected to abort execution for unhandled errors and thus prevent incorrect execution. In fact, all introspection-instrumented tools prevented this buffer overflow by aborting execution.

LightFTP.

LightFTP is a small FTP server.666https://github.com/hfiref0x/LightFTP/ A logging function writelogentry() in version 1.1 of LightFTP was vulnerable to a buffer overflow that allowed denial of service or remote code execution (see CVE-2017-1000218). As shown below, the program added log entries to a buffer with a hard-coded size; as the log entries depended on user input that was restricted by another, larger constant, a buffer overflow could be triggered:

char _text[512];
// ...
if (logtext1)
    strcat(_text, logtext1);
if (logtext2)
    strcat(_text, logtext2);
strcat(_text, CRLF);

The introspection interceptor for strcat() mitigated the error without crashing the FTP server. Note that our mitigation truncated the log entry, but allowed subsequent requests to be handled successfully.

6 Performance Evaluation

Figure 1: Throughput on LightFTP and Dnsmasq.

To determine the performance of the introspection-based interceptors, we used LightFTP and Dnsmasq, which are the servers we also investigated in our CVE case study. We selected them for their high attack surface and because they are expected to be highly available. We evaluated the performance of ASan and Intel MPX both with and without the introspection interceptors; SoftBound failed to execute the servers, as explained above. Further, to establish a baseline, we measured the performance of C programs compiled with the Clang compiler [13] without using any bug-mitigation mechanisms. For all systems, we turned on compiler optimizations by using the -O3 flag. We measured the throughput by means of the load-testing tool JMeter version 3.3. We configured JMeter to use 4 threads, each of which each sent 250 requests to simulate multiple concurrent users using the built-in FTP sampler and the UDP Protocol Support plugin. As the Intel MPX instructions are not thread-safe [19], we also evaluated all tools using only 1 thread. We performed each measurement 10 times to account for variability. Our setup consisted of a quad-core Intel Core i7-6700HQ CPU at 2.60GHz on Ubuntu version 17.10 (with kernel 4.13.0-32-generic) with 16 GB of memory.

Figure 1 shows boxplots of the results for LightFTP and Dnsmasq. On LightFTP, the performance overhead for using introspection was below 1% for ASan; MPX was even slightly faster when introspection was used. On Dnsmasq, employing introspection caused a slowdown of around 1% when using only one thread for both ASan and MPX. The performance difference to the baseline was negligible on LightFTP, and up to 11% on Dnsmasq (between Clang and ASan with introspection), which suggests that the applications’ performance was dominated by factors other than instrumentation cost (e.g., networking overhead). Thus, our measurements cannot be generalized to CPU-bound benchmarks.

To quantify the overhead on CPU-bound benchmarks, we also evaluated the approaches on the SPEC2006 INT benchmarks, which consist of 12 benchmarks. We excluded all C++ benchmarks (471.omnetpp, 473.astar, and 483.xalancbmk), which we expected to make little use of C functions and thus of our interceptors. Further, we excluded all benchmarks in which the tools detected memory safety errors (400.perlbench and 403.gcc). ASan detected memory leaks in two benchmarks (445.gobmk and 464.h264ref), and since we investigated only buffer overflows in this work, we disabled memory leak detection to also run them. SoftBound in its original and introspection versions detected memory safety errors in all but one benchmark (458.sjeng), which were presumably false positives. MPX had an additional known false positive [19] in one benchmark (429.mcf), so we excluded this benchmark for MPX.

Figure 2 shows the execution times of the SPECInt2006 benchmarks relative to Clang -O3 as a baseline. On four of the seven benchmarks (429.mcf, 456.hmmer, 458.sjeng, 462.libquantum), the performance overhead was negligible because no interceptors were executed in code that contributed to the overall run-time performance of the respective benchmark. For SoftBound, the introspection overhead was 3% on the only benchmark that it could execute. Using introspection with ASan resulted in higher overheads, namely 140% on h264ref, 43% on bzip2, and 81% on gobmk. For MPX, the performance overhead of introspection was relatively low, with maximum overheads of 13% on bzip2 and 6% on gobmk.

Figure 2: Execution times on the SpecInt2006 benchmarks.

We also executed micro-benchmarks, measuring the direct overhead of interceptors. For example, we evaluated the performance of the strlen() interceptor, which directly relies on _size_right() to call the safer strnlen() function. For SoftBound, the overhead was not measurable. For Intel MPX, the overhead was 2 for strings with a length of 10; for longer strings (e.g., a length of 1000) the overhead was not measurable. The overhead for ASan was the highest, as our size_right() implementation has to traverse the shadow memory, which depends linearly on the length of the string. Its overhead varied between 2 and 10 with different string lengths.

7 Discussion

Availability.

We have demonstrated that our introspection-based libc interceptors are an effective means of mitigating the effects of buffer overflows. Our main idea is to use run-time information that is tracked by existing tools to prevent buffer overflows and to increase the availability of applications. Using the introspection-based interceptors is useful only in production, because during development and testing it would be preferable to abort execution so that the programmer can fix bugs that cause errors.

Complementarity.

We have designed our approach to complement existing approaches for handling buffer overflows. Our idea is that, for important functions, programmers can implement custom semantics that mitigate the effects of buffer overflows. For buffer overflows in other functions or in user-level code, existing memory tools would continue to detect out-of-bounds accesses and would abort execution in the case of an error. Alternatively, the interceptors could also be used with the original failure-oblivious computing approach as a fallback for functions that are not guarded by introspection checks.

Performance.

The overhead of introspection and our interceptors depends mainly on how efficiently a tool tracks bounds information. Our evaluation on servers suggests that the overhead of introspection is often small compared to the cost of network communication, making introspection especially applicable for servers. Our evaluation on the CPU-bound SPEC benchmarks also seems to suggest that libc functions are typically not part of the code that significantly contributes to the overall performance of a program. While the MPX-based introspection overhead was low on all benchmarks, only the ASan-based implementation caused larger overheads on three benchmarks. Overall, introspection-based libc functions are feasible with a low overhead for approaches that maintain explicit bounds information (e.g., Intel MPX or SoftBound), but result in higher overheads for approaches in which bounds information must be computed (e.g., in ASan). Furthermore, our implementation could be made more efficient by using introspection directly in the libc functions.

Implementation.

We have demonstrated implementations of the _size_right() function for three popular bug-finding and bug-mitigation approaches and believe that implementing this function in many others (e.g., libcrunch [10, 11]) is also straightforward. Some tools cannot give precise estimates for all pointers, which makes our approach less effective. For example, binary-instrumentation tools such as Valgrind [18] and Dr. Memory [3] cannot reliably determine the size of buffers located on the stack. Other approaches track run-time information only for specific types of allocations (e.g., stack buffers [2]). Furthermore, some tools give rough estimates in general or round up allocation sizes [1, 2, 6]; for example, after evaluating our approach with low-fat pointer checking [6, 8], we found that rounding up allocation sizes alone mitigated several of the buffer overflows that we investigated.777EffectiveSan [7], an extension of the low-fat pointer approach, provides accurate bounds but has not been released to the public as of June 2018. Note that conservative estimates (e.g., the maximum integer value if no information is available) ensure correct execution, but might result in undetected errors.

8 Related Work

Failure-oblivious computing.

Rinard et al. coined the term failure-oblivious computing, where illegal read accesses yield predefined values and out-of-bounds write accesses are ignored [25]. An extension of this work are boundless memory blocks, where out-of-bounds writes store the value in a hash map that can be returned for out-of-bounds reads to that address [4, 12, 26]. Furthermore, Long et al. extended failure-oblivious computing by also covering divide-by-zero errors and NULL-pointer dereferences [14]. In contrast to these approaches, introspection enables programmers to handle out-of-bounds accesses by taking into account the semantics of a function. However, the drawback of our approach is that library developers must implement these checks manually.

Failure-oblivious computing models.

Durieux et al. studied failure-oblivious computing behaviors [9]. Their findings suggest that for many failures, multiple alternative strategies exist that can mitigate the error. For example, to mitigate a NULL-pointer dereference the access could be ignored, but the pointer could also be initialized with the address of a newly-created or existing object.

Monitored execution.

Sidiroglou et al. devised a system that monitors an application for failures such as buffer overflows [29]

. If a fault occurs, the current function is aborted and—based on heuristics—an appropriate value is returned. In order to avoid crashes because a pointer returns

NULL, the heuristics take into account whether the parent function dereferences the pointer thereafter. While this approach takes into account the context of the fault, it lacks the ability of our introspection approach to benefit from programmer knowledge.

Libsafe.

Libsafe replaces libc functions with enhanced versions that prevent buffer overflows from going beyond the stack frame [2]. It achieves this by traversing frames to determine their bounds and aborting the program if the bounds are exceeded. While we tried implementing the introspection function using the traversal logic, we found that it is based on assumptions such as the location of the stack, which no longer hold with modern mitigation techniques such as address space layout randomization. Additionally, libsafe does not handle out-of-bounds reads well, for which our approach, in contrast, can compute meaningful results, for example, by letting strlen() return the length of the buffer underlying the string if it is unterminated.

9 Conclusion

In this paper, we have presented how implementation of an introspection function that returns the length of an object can be used to implement failure-oblivious computing mechanisms. We have also shown that such a mechanism is useful in mitigating real-world errors and that the performance overhead when implemented in approaches such as Intel MPX is negligible. For reproducibility and to facilitate further research, we distribute all artifacts and experimentation scripts at https://github.com/introspection-libc/main.

References

  • [1] Akritidis, P., Costa, M., Castro, M., Hand, S.: Baggy bounds checking: An efficient and backwards-compatible defense against out-of-bounds errors. In: Proceedings of the 18th Conference on USENIX Security Symposium. pp. 51–66. SSYM’09, USENIX Association, Berkeley, CA, USA (2009)
  • [2] Baratloo, A., Singh, N., Tsai, T.: Libsafe: Protecting critical elements of stacks. White Paper (1999), http://www.research.avayalabs.com/project/libsafe
  • [3] Bruening, D., Zhao, Q.: Practical memory checking with dr. memory. In: Proceedings of the 9th Annual IEEE/ACM International Symposium on Code Generation and Optimization. pp. 213–223. CGO ’11, IEEE Computer Society, Washington, DC, USA (2011)
  • [4] Brunink, M., Susskraut, M., Fetzer, C.: Boundless memory allocations for memory safety and high availability. In: Proceedings of the 2011 IEEE/IFIP 41st International Conference on Dependable Systems&Networks. pp. 13–24. DSN ’11, IEEE Computer Society, Washington, DC, USA (2011). https://doi.org/10.1109/DSN.2011.5958203
  • [5] Cowan, C., Wagle, P., Pu, C., Beattie, S., Walpole, J.: Buffer overflows: Attacks and defenses for the vulnerability of the decade. In: DARPA Information Survivability Conference and Exposition, 2000. DISCEX’00. Proceedings. vol. 2, pp. 119–129. IEEE (2000)
  • [6] Duck, G.J., Yap, R.H.C.: Heap bounds protection with low fat pointers. In: Proceedings of the 25th International Conference on Compiler Construction. pp. 132–142. CC 2016, ACM, New York, NY, USA (2016). https://doi.org/10.1145/2892208.2892212
  • [7] Duck, G.J., Yap, R.H.C.: Effectivesan: Type and memory error detection using dynamically typed c/c++. In: Proceedings of the 39th ACM SIGPLAN Conference on Programming Language Design and Implementation. pp. 181–195. PLDI 2018, ACM, New York, NY, USA (2018). https://doi.org/10.1145/3192366.3192388
  • [8] Duck, G.J., Yap, R.H., Cavallaro, L.: Stack bounds protection with low fat pointers. In: Symposium on Network and Distributed System Security (2017)
  • [9] Durieux, T., Hamadi, Y., Yu, Z., Baudry, B., Monperrus, M.: Exhaustive exploration of the failure-oblivious computing search space. In: Proc. of the Int. Conf. on Sotware Testing and Verification (ICST). ICST’18 (Apr 2018)
  • [10] Kell, S.: Towards a dynamic object model within unix processes. In: 2015 ACM International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software (Onward!). pp. 224–239. Onward! 2015, ACM, New York, NY, USA (2015). https://doi.org/10.1145/2814228.2814238
  • [11] Kell, S.: Dynamically diagnosing type errors in unsafe code. In: Proceedings of the 2016 ACM SIGPLAN International Conference on Object-Oriented Programming, Systems, Languages, and Applications. pp. 800–819. OOPSLA 2016, ACM, New York, NY, USA (2016). https://doi.org/10.1145/2983990.2983998
  • [12] Kuvaiskii, D., Oleksenko, O., Arnautov, S., Trach, B., Bhatotia, P., Felber, P., Fetzer, C.: SGXBOUNDS: Memory safety for shielded execution. In: Proceedings of the Twelfth European Conference on Computer Systems. pp. 205–221. EuroSys ’17, ACM, New York, NY, USA (2017). https://doi.org/10.1145/3064176.3064192
  • [13] Lattner, C., Adve, V.: Llvm: a compilation framework for lifelong program analysis transformation. In: CGO 2004. pp. 75–86 (March 2004)
  • [14] Long, F., Sidiroglou-Douskos, S., Rinard, M.: Automatic runtime error repair and containment via recovery shepherding. In: Proceedings of the 35th ACM SIGPLAN Conference on Programming Language Design and Implementation. pp. 227–238. PLDI ’14, ACM, New York, NY, USA (2014). https://doi.org/10.1145/2594291.2594337
  • [15] Nagarakatte, S., Zhao, J., Martin, M.M., Zdancewic, S.: Softbound: Highly compatible and complete spatial memory safety for c. In: Proceedings of the 30th ACM SIGPLAN Conference on Programming Language Design and Implementation. pp. 245–258. PLDI ’09, ACM, New York, NY, USA (2009). https://doi.org/10.1145/1542476.1542504
  • [16] Nagarakatte, S., Zhao, J., Martin, M.M., Zdancewic, S.: Cets: Compiler enforced temporal safety for c pp. 31–40 (2010). https://doi.org/10.1145/1806651.1806657
  • [17] Nethercote, N., Seward, J.: How to shadow every byte of memory used by a program. In: Proceedings of the 3rd International Conference on Virtual Execution Environments. pp. 65–74. VEE ’07, ACM, New York, NY, USA (2007). https://doi.org/10.1145/1254810.1254820
  • [18] Nethercote, N., Seward, J.: Valgrind: A framework for heavyweight dynamic binary instrumentation. In: Proceedings of the 28th ACM SIGPLAN Conference on Programming Language Design and Implementation. pp. 89–100. PLDI ’07, ACM, New York, NY, USA (2007). https://doi.org/10.1145/1250734.1250746
  • [19] Oleksenko, O., Kuvaiskii, D., Bhatotia, P., Felber, P., Fetzer, C.: Intel mpx explained: A cross-layer analysis of the intel mpx system stack. Proc. ACM Meas. Anal. Comput. Syst. 2(2), 28:1–28:30 (Jun 2018). https://doi.org/10.1145/3224423
  • [20] Rigger, M., Grimmer, M., Wimmer, C., Würthinger, T., Mössenböck, H.: Bringing low-level languages to the jvm: Efficient execution of llvm ir on truffle. In: Proceedings of the 8th International Workshop on Virtual Machines and Intermediate Languages. pp. 6–15. VMIL 2016, ACM, New York, NY, USA (2016). https://doi.org/10.1145/2998415.2998416
  • [21] Rigger, M., Schatz, R., Grimmer, M., Mössenböck, H.: Lenient execution of c on a java virtual machine: Or: How i learned to stop worrying and run the code. In: Proceedings of the 14th International Conference on Managed Languages and Runtimes. pp. 35–47. ManLang 2017, ACM, New York, NY, USA (2017). https://doi.org/10.1145/3132190.3132204
  • [22] Rigger, M., Schatz, R., Mayrhofer, R., Grimmer, M., Mössenböck, H.: Sulong, and Thanks For All the Bugs: Finding Errors in C Programs by Abstracting from the Native Execution Model. In: Proceedings of the Twenty-Third International Conference on Architectural Support for Programming Languages and Operating Systems. ASPLOS 2018. https://doi.org/10.1145/3173162.3173174
  • [23] Rigger, M., Schatz, R., Mayrhofer, R., Grimmer, M., Mössenböck, H.: Introspection for C and its Applications to Library Robustness. The Art, Science, and Engineering of Programming (2) (2018). https://doi.org/10.22152/programming-journal.org/2018/2/4
  • [24] Rinard, M.: Acceptability-oriented computing. In: Companion of the 18th Annual ACM SIGPLAN Conference on Object-oriented Programming, Systems, Languages, and Applications. pp. 221–239. OOPSLA ’03, ACM, New York, NY, USA (2003). https://doi.org/10.1145/949344.949402
  • [25] Rinard, M., Cadar, C., Dumitran, D., Roy, D.M., Leu, T., Beebee, Jr., W.S.: Enhancing server availability and security through failure-oblivious computing. In: Proceedings of the 6th Conference on Symposium on Opearting Systems Design & Implementation - Volume 6. pp. 21–21. OSDI’04, USENIX Association, Berkeley, CA, USA (2004)
  • [26] Rinard, M.C.: Failure-oblivious computing and boundless memory blocks (2005), technical Report
  • [27] Serebryany, K., Bruening, D., Potapenko, A., Vyukov, D.: Addresssanitizer: A fast address sanity checker. In: USENIX Annual Technical Conference. pp. 309–318 (2012)
  • [28] Shacham, H.: The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86). In: Proceedings of the 14th ACM Conference on Computer and Communications Security. pp. 552–561. CCS ’07, ACM, New York, NY, USA (2007). https://doi.org/10.1145/1315245.1315313
  • [29] Sidiroglou, S., Locasto, M.E., Boyd, S.W., Keromytis, A.D.: Building a reactive immune system for software services. In: Proceedings of the Annual Conference on USENIX Annual Technical Conference. pp. 11–11. ATEC ’05, USENIX Association, Berkeley, CA, USA (2005)
  • [30] Song, D., Lettner, J., Rajasekaran, P., Na, Y., Volckaert, S., Larsen, P., Franz, M.: Sok: Sanitizing for security. IEEE Symposium on Security and Privacy (S&P’19) Accepted. To Appear.
  • [31] Strackx, R., Younan, Y., Philippaerts, P., Piessens, F., Lachmund, S., Walter, T.: Breaking the memory secrecy assumption. In: Proceedings of the Second European Workshop on System Security. pp. 1–8. EUROSEC ’09, ACM, New York, NY, USA (2009). https://doi.org/10.1145/1519144.1519145
  • [32] Szekeres, L., Payer, M., Wei, T., Song, D.: Sok: Eternal war in memory. In: Proceedings of the 2013 IEEE Symposium on Security and Privacy. pp. 48–62. SP ’13, IEEE Computer Society, Washington, DC, USA (2013). https://doi.org/10.1109/SP.2013.13
  • [33] The MITRE Corporation: Common vulnerabilities and exposures, https://cve.mitre.org/
  • [34] van der Veen, V., dutt Sharma, N., Cavallaro, L., Bos, H.: Memory errors: The past, the present, and the future. In: Proceedings of the 15th International Conference on Research in Attacks, Intrusions, and Defenses. pp. 86–106. RAID’12, Springer-Verlag, Berlin, Heidelberg (2012), https://doi.org/10.1007/978-3-642-33338-5_5
  • [35] Watson, R.N.M., Woodruff, J., Neumann, P.G., Moore, S.W., Anderson, J., Chisnall, D., Dave, N., Davis, B., Gudka, K., Laurie, B., Murdoch, S.J., Norton, R., Roe, M., Son, S., Vadera, M.: Cheri: A hybrid capability-system architecture for scalable software compartmentalization. In: 2015 IEEE Symposium on Security and Privacy. pp. 20–37 (May 2015). https://doi.org/10.1109/SP.2015.9
  • [36] Younan, Y., Joosen, W., Piessens, F.: Runtime countermeasures for code injection attacks against c and c++ programs. ACM Comput. Surv. 44(3), 17:1–17:28 (Jun 2012). https://doi.org/10.1145/2187671.2187679