Skip to content

Instantly share code, notes, and snippets.

@thestinger
Last active February 11, 2016 23:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thestinger/cd714b870939417d2168 to your computer and use it in GitHub Desktop.
Save thestinger/cd714b870939417d2168 to your computer and use it in GitHub Desktop.
// This double-free is detected with 100% reliability in CopperheadOS via the
// malloc quarantine. The malloc quarantine uses a ring buffer to provide a
// guaranteed baseline delay and a hash table for detecting double frees. A
// double free can also be detected after allocations are flushed from the
// quarantine, but only if the slot is still free.
//
// /data/data/test/test(688) in free(): error: double free 0x8e503300
// Aborted
#include <stdlib.h>
static const size_t max_allocation_size = 128;
// prevent the compiler from optimizing out calls to malloc
__attribute__((optimize(0)))
int main(void) {
void *p[32]; // to be freed
void *q[sizeof(p) / sizeof(p[0])]; // to be kept
// make some allocations
for (size_t i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
size_t size = arc4random_uniform(max_allocation_size + 1);
p[i] = malloc(size);
q[i] = malloc(size);
if (!p[i] || !q[i]) {
return 1;
}
}
// release the allocations
for (size_t i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
free(p[i]);
}
// defeat double-free detection without the quarantine
for (size_t i = 0; i < 1024; i++) {
malloc(arc4random_uniform(max_allocation_size + 1));
}
// double-free a random allocation
free(p[arc4random_uniform(sizeof(p) / sizeof(p[0]))]);
return 0;
}
// This write-after-free is detected with 100% reliability in CopperheadOS via
// the malloc quarantine and junk filling. The malloc quarantine uses a ring
// buffer to provide a guaranteed baseline delay and the junk filled on free is
// validated when allocations are flushed from the quarantine and at exit.
//
// /data/data/test/test(2172) in validate_delayed_chunks(): error: use after free 0xa60e1200
// Aborted
#include <stdlib.h>
static const size_t max_allocation_size = 128;
// prevent the compiler from optimizing out calls to malloc
__attribute__((optimize(0)))
int main(void) {
char *p[32]; // to be freed
char *q[sizeof(p) / sizeof(p[0])]; // to be kept
// make some allocations
for (size_t i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
size_t size = arc4random_uniform(max_allocation_size) + 1;
p[i] = malloc(size);
q[i] = malloc(size);
if (!p[i] || !q[i]) {
return 1;
}
}
// release the allocations
for (size_t i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
free(p[i]);
}
// write-after-free into a random allocation
p[arc4random_uniform(sizeof(p) / sizeof(p[0]))][0] = 'a';
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment