#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <signal.h>
void *mymalloc(size_t len)
{
void *buf;
size_t pages = (len & PAGE_MASK) + 2;
size_t offset = PAGE_SIZE - (len & ~PAGE_MASK);
if(offset < sizeof(size_t))
{
pages++;
offset += PAGE_SIZE;
}
if((buf = mmap(NULL, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)) == -1)
{
perror("mymalloc/mmap");
exit(1);
}
*(size_t *)buf = len;
*(size_t *)(buf+offset+len) = len;
if(mprotect(buf+offset+len, PAGE_SIZE, PROT_NONE) == -1)
{
perror("mymalloc/mprotect");
exit(1);
}
return buf+offset;
}
void myfree(void *buf)
{
void *start = (long)buf & PAGE_MASK;
size_t offset = (long)buf & ~PAGE_MASK;
/* Will segfault here on double-free */
size_t len = *(size_t *)start;
/* Check to see if we had to tack on another page in mymalloc */
if(buf - start < sizeof(size_t))
{
start -= PAGE_SIZE;
len = *(size_t *)start;
}
/* Unprotect our memory */
if(mprotect(buf+len, PAGE_SIZE, PROT_READ) == -1)
{
perror("myfree/mprotect");
raise(SIGSEGV);
}
/* Check to make sure lengths are consistant. If not, advise user to try
using the (not yet written) underflow version of this library */
if(*(size_t *)(buf + len) != *(size_t *)start)
{
fprintf(stderr, "Error: heap corruption. Inconsistant allocation "
"sizes. Try using the underflow option to pinpoint source "
"of error\n");
raise(SIGSEGV);
}
if(munmap(start, len+offset+PAGE_SIZE) == -1)
{
perror("myfree/munmap");
raise(SIGSEGV);
}
if(mmap(start, len+offset+PAGE_SIZE, PROT_NONE,
MAP_ANON | MAP_FIXED | MAP_PRIVATE, 0, 0) == -1)
{
perror("myfree/mremap");
}
}