X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Flizard-safe.c;h=6d0b10c952b585e0cd93cf9bd24583f53fd9fb67;hb=4deb7fd75ea1306e943ab414efca26b1951cfd23;hp=fb45f8bf17f8a6d83b694485f8ed10dc80f009fd;hpb=159f3fd2f4b044788fc71208855ed1a846b20949;p=libucw.git diff --git a/lib/lizard-safe.c b/lib/lizard-safe.c index fb45f8bf..6d0b10c9 100644 --- a/lib/lizard-safe.c +++ b/lib/lizard-safe.c @@ -21,28 +21,28 @@ 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 = handle_signal(SIGSEGV); return buf; } void lizard_free(struct lizard_buffer *buf) { - munmap(buf->ptr, buf->len); + munmap(buf->start, buf->len + PAGE_SIZE); + signal(SIGSEGV, buf->old_sigsegv_handler); xfree(buf); } static jmp_buf safe_decompress_jump; static void -sigsegv_handler(int UNUSED whatsit) +sigsegv_handler(void) { log(L_ERROR, "SIGSEGV caught in lizard_decompress()"); longjmp(safe_decompress_jump, 1); @@ -55,27 +55,28 @@ lizard_decompress_safe(byte *in, struct lizard_buffer *buf, uns expected_length) * is caught in the case of buffer-overflow. The function is not re-entrant * because of a static longjmp handler. */ { - 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); + volatile my_sighandler_t old_handler = signal_handler[SIGSEGV]; + signal_handler[SIGSEGV] = sigsegv_handler; int len, err; 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; } - signal(SIGSEGV, old_handler); - mprotect(buf->ptr + lock_offset, PAGE_SIZE, PROT_READ | PROT_WRITE); + signal_handler[SIGSEGV] = old_handler; errno = err; return len; }