Double Frees in Chrome's Partition Alloc - part 2
Dr Silvio Cesare
@silviocesare
Summary
PartitionAlloc is the hardened heap allocator used in Google's Chrome web browser. It is susceptible to a number of attacks. This blog post describes the second attack in a series of posts. I will talk about double frees and how to make an allocation request return an arbitrary pointer. This can be used with application-logic to develop an arbitrary write primitive.Introduction
In heap allocators, freelists maintain a group of free memory chunks that are available to be recycled by an allocation request. Freelist poisoning corrupts this list and injects a "fake chunk" pointer. A later allocation will return this fake chunk pointer. So it is possible to make an allocation request return an arbitrary pointer.A double free often creates a cycle in the freelist. When a chunk is returned by an allocation request, the chunk still remains in the freelist. Thus, if an attacker writes to that chunk, it is use-after-free and akin to freelist poisoning.
ParitionAlloc Double Frees
PartitionAlloc, like many other allocators, has a trivial mitigation against double frees. It simply checks the last freed pointer with the pointer currently being freed. Here is an example of a trivial double free.And let's see the mitigation in effect, which triggers a SIGILL:
A simple method to defeat this trivial mitigation is to interleave the free of another pointer between the double free. This will create a cycle in the underlying freelist and subsequent allocations will reflect this cycle.
And we can see the freelist cycle produces an infinite number of identical allocations reflecting the cycle that was created.
The important thing to note is that when one of those chunks is allocated, it still remains on the freelist. Thus, if we overwrite the data in a chunk, it's effectively the same as a use-after-free. Therefore, we can employ freelist poisoning. Let's do that:
Let's run our complete exploit:
We can see we made PartitionAlloc return an arbitrary pointer. The application logic let us write to that, and we made the foo variable our desired value.