UAF Sanitization Reimagined: A Look at a Lightweight Solution
UAF, or use after free, is a common vulnerability in C/C++ programs. It occurs when a pointer to a freed memory region is used after the memory is freed. This can lead to a variety of attacks, including code execution, information disclosure, and denial of service. The most common way to detect UAF is to use a sanitizer, which is a tool that can detect UAF at runtime.
The most popular sanitizer is ASAN, which is a part of the LLVM compiler infrastructure. ASAN is a powerful tool that can detect a variety of memory errors, including UAF. However, ASAN is not lightweight enough. ASAN need to use shadow memory to track the status of each byte in the heap. It is not convenient to use in some scenarios, such as embedded systems.
In USENIX Security 2023, some reasearcher from Georgia Institute of Technology proposed a new UAF defense mechanism called PUMM. PUMM is based on the observation that if allocated memory is always not freed, it is unlikely to be used after free. However, never freeing memory is not a good practice, because it will lead great memory overhead. Therefore, PUMM uses a simple heuristic algorithm to determine when to free memory.
Specifically, PUMM observes that most program are implemented with a main task loop that iterates once per task until an exit condition or signal occurs. Local variables are initialized at the beginning of each iteration, and the current task does not depend on data from prior ones. Based on this observation, PUMM frees memory at the end of each iteration.
PUMM maintain a list to store those pointers has not been freed. When the program call
free function, PUMM will not free the memory immediately, but add the pointer into the list. When the program reach the end of the main task loop, PUMM will free all the pointers in the list. If we rethink the PUMM, we may find that the list can also tell us that use after free can only happened on the pointers in the list. It means that if an use after free happens, it must read or write the memory region that stored in the list. Otherwise, the PUMM’s method will not work.
Upon observation, it can be seen that PUMM maintains a list of pointers that have not been freed, and use-after-free errors can only occur on these pointers. PUMM is not a sanitizer, but rather a defense mechanism that can prevent use-after-free errors. While it cannot detect use-after-free errors, it can effectively prevent them. PUMM only incurs a 2.04% runtime overhead and 16.48% memory overhead. By building on top of PUMM, additional mechanisms can be implemented to enable PUMM to detect use-after-free errors.
There are two types of use-after-free errors: write-after-free and read-after-free. To detect write-after-free errors, we fill the freed memory region with random canary values. If a write-after-free error occurs, the canary values will be overwritten. By checking the canary values, we can determine if a write-after-free error occurred when the memory region was freed. It’s worth noting that we only add twice consecutive memory reads/writes to all allocated memory regions, so the overhead of this mechanism should be minimal.
To detect read-after-free errors, we can use the shadow memory method. We can use a similar method as write-after-free. Although read memory will not change the memory region, we can allocate a shadow memory region for each memory region and instrument a write operation to the corresponding shadow memory region. If a read-after-free error occurs, the shadow memory region will be modified.
Some people may think that the shadow memory method is not lightweight enough and will incur significant runtime and memory overhead. However, we can carefully estimate the memory overhead of the shadow memory method. Note that almost all allocated memory regions have a size that is a multiple of eight, and we only care whether the value on the shadow memory region is zero or not (zero means the memory has not been modified). Therefore, we can only use 1 bit to represent 8 bytes. This means that the memory overhead of the shadow memory method is only 1/64 or 1.56%.
In terms of runtime overhead, we don’t need to instrument all read operations. There are several optimization methods we can use to reduce instrumentation. For example:
- We can skip instrumentation of a read operation A if A and another read operation B write to the same memory region, A is dominated or post-dominated by B, and there is no free operation between A and B.
- We can also skip instrumentation of a read operation A if A and a write operation B operate on the same memory region, A is dominated or post-dominated by B, and there is no free operation between A and B.
In theory, we can skip instrumentation of up to 70% of read operations. Additionally, our instrumentation does not introduce new basic blocks. Therefore, the expected runtime overhead should be lower than 10%.
Why do I need to implement an idea I’m raving about? ChatGPT generate the implementation and evaluation part.
In conclusion, detecting and preventing use-after-free errors is critical for ensuring software reliability and security. Various techniques, such as PUMM, can be used to defend against these types of errors. While PUMM itself cannot detect use-after-free errors, it can prevent them by maintaining a list of pointers that have not been freed. To improve PUMM’s capabilities, we can add mechanisms such as canary checks and shadow memory to detect write-after-free and read-after-free errors. These mechanisms have a relatively low runtime and memory overhead and can greatly enhance the effectiveness of PUMM. Additionally, we can optimize the instrumentation of read operations to further reduce the overhead of these techniques. By using a combination of these techniques, we can improve the reliability and security of software systems and prevent potentially catastrophic consequences of use-after-free errors.
- Post title：UAF Sanitization Reimagined: A Look at a Lightweight Solution
- Post author：Zheng Yu
- Create time：2023-02-19 11:58:43
- Post link：https://dataisland.org/2023/02/19/new-uaf-sanitizer/
- Copyright Notice：All articles in this blog are licensed under BY-NC-SA unless stating additionally.