]> mj.ucw.cz Git - libucw.git/blobdiff - lib/lizard-safe.c
OK, buck2obj looks nice now, so let us add it
[libucw.git] / lib / lizard-safe.c
index c615acc4b131a704ee046cba9b3575dfa11dd13b..1c46cbdcbb58d211cd27cfb5a316a8917f1d64ae 100644 (file)
@@ -22,12 +22,14 @@ struct lizard_buffer *
 lizard_alloc(uns max_len)
 {
   struct lizard_buffer *buf = xmalloc(sizeof(struct lizard_buffer));
-  buf->len = ALIGN(max_len, PAGE_SIZE);
+  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;
 }
 
@@ -35,15 +37,18 @@ void
 lizard_free(struct lizard_buffer *buf)
 {
   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
@@ -53,27 +58,26 @@ 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);
+  uns lock_offset = ALIGN(expected_length + 3, PAGE_SIZE);     // +3 due to the unaligned access
   if (lock_offset > buf->len)
   {
     errno = EFBIG;
     return -1;
   }
-  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);
-  errno = err;
+  signal_handler[SIGSEGV] = old_handler;
   return len;
 }