struct lizard_buffer *
lizard_alloc(uns max_len)
{
- static byte *zero = "/dev/zero";
- int fd = open(zero, O_RDWR);
- if (fd < 0)
- die("open(%s): %m", zero);
struct lizard_buffer *buf = xmalloc(sizeof(struct lizard_buffer));
- buf->len = ALIGN(max_len + PAGE_SIZE, PAGE_SIZE);
- buf->ptr = mmap(NULL, buf->len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (buf->ptr == MAP_FAILED)
- die("mmap(%s): %m", zero);
+ buf->len = ALIGN(max_len + 3, PAGE_SIZE); // +3 due to the unaligned access
+ buf->start = mmap(NULL, buf->len + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (buf->start == MAP_FAILED)
+ die("mmap(anonymous): %m");
+ if (mprotect(buf->start + buf->len, PAGE_SIZE, PROT_NONE) < 0)
+ die("mprotect: %m");
+ buf->old_sigsegv_handler = xmalloc(sizeof(struct sigaction));
+ handle_signal(SIGSEGV, buf->old_sigsegv_handler);
return buf;
}
void
lizard_free(struct lizard_buffer *buf)
{
- munmap(buf->ptr, buf->len);
+ munmap(buf->start, buf->len + PAGE_SIZE);
+ unhandle_signal(SIGSEGV, buf->old_sigsegv_handler);
+ xfree(buf->old_sigsegv_handler);
xfree(buf);
}
static jmp_buf safe_decompress_jump;
-static void
-sigsegv_handler(int UNUSED whatsit)
+static int
+sigsegv_handler(int signal UNUSED)
{
log(L_ERROR, "SIGSEGV caught in lizard_decompress()");
longjmp(safe_decompress_jump, 1);
+ return 1;
}
int
* is caught in the case of buffer-overflow. The function is not re-entrant
* because of a static longjmp handler. */
{
- volatile uns lock_offset = ALIGN(expected_length, PAGE_SIZE);
- if (lock_offset + PAGE_SIZE > buf->len)
+ uns lock_offset = ALIGN(expected_length + 3, PAGE_SIZE); // +3 due to the unaligned access
+ if (lock_offset > buf->len)
{
errno = EFBIG;
return -1;
}
- mprotect(buf->ptr + lock_offset, PAGE_SIZE, PROT_NONE);
- volatile sighandler_t old_handler = signal(SIGSEGV, sigsegv_handler);
- int len, err;
+ volatile sh_sighandler_t old_handler = signal_handler[SIGSEGV];
+ signal_handler[SIGSEGV] = sigsegv_handler;
+ int len;
if (!setjmp(safe_decompress_jump))
{
+ buf->ptr = buf->start + buf->len - lock_offset;
len = lizard_decompress(in, buf->ptr);
- err = errno;
}
else
{
+ buf->ptr = NULL;
len = -1;
- err = EFAULT;
+ errno = EFAULT;
}
- signal(SIGSEGV, old_handler);
- mprotect(buf->ptr + lock_offset, PAGE_SIZE, PROT_READ | PROT_WRITE);
- errno = err;
+ signal_handler[SIGSEGV] = old_handler;
return len;
}