[Forensics-changes] [yara] 02/368: Add exception handling when scanning memory blocks

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:30:04 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.5.0
in repository yara.

commit db22ffda588b9b3abc619f8a2f616d0be57e9335
Author: Hilko Bengen <bengen at debian.org>
Date:   Thu Jun 25 18:58:27 2015 +0200

    Add exception handling when scanning memory blocks
    
    Unix: signal handler for SIGBUS + sigsetjmp/siglongjmp
    Win32: vectored exception handler + setjmp/longjmp
    
    This should eliminate crashes when accessing the contents of files
    that turn out to be unreadable after they have successfully beea
    mapped into memory.
    
    This can occur if the mapped file is truncated (Unix) or if the
    filesystem is corrupted.
---
 libyara/exception.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 libyara/rules.c     | 52 +++++++++++++++++------------
 2 files changed, 127 insertions(+), 21 deletions(-)

diff --git a/libyara/exception.h b/libyara/exception.h
new file mode 100644
index 0000000..4a1bd5a
--- /dev/null
+++ b/libyara/exception.h
@@ -0,0 +1,96 @@
+#ifndef _EXCEPTION_H_
+#define _EXCEPTION_H_
+
+#if _WIN32
+
+#include <windows.h>
+#include <setjmp.h>
+
+#define YR_EXCEPT(_try_clause_, _catch_clause_) \
+  _try_clause_
+
+jmp_buf *exc_jmp_buf[MAX_THREADS];
+
+static LONG CALLBACK exception_handler(
+    PEXCEPTION_POINTERS ExceptionInfo)
+{
+  switch(ExceptionInfo->ExceptionRecord->ExceptionCode) {
+  case EXCEPTION_IN_PAGE_ERROR:
+  case EXCEPTION_ACCESS_VIOLATION:
+    break;
+  default:
+    return EXCEPTION_CONTINUE_SEARCH;
+  }
+  int tidx = yr_get_tidx();
+  if (tidx != -1 && exc_jmp_buf[tidx] != NULL) {
+    longjmp(*exc_jmp_buf[tidx], 1);
+  }
+  /* We should not reach this point. */
+  abort();
+}
+
+#define YR_TRYCATCH(_try_clause_,_catch_clause_)                        \
+  do {                                                                  \
+    HANDLE exh = AddVectoredExceptionHandler(1, exception_handler);     \
+    int tidx = yr_get_tidx();                                           \
+    if (tidx == -1) {                                                   \
+      abort();                                                          \
+    }                                                                   \
+    jmp_buf jb;                                                         \
+    exc_jmp_buf[tidx] = &jb;                                            \
+    if (setjmp(jb) == 0)                                                \
+      { _try_clause_ }                                                  \
+    else                                                                \
+      { _catch_clause_ }                                                \
+    exc_jmp_buf[tidx] = NULL;                                           \
+    RemoveVectoredExceptionHandler(exh);                                \
+  } while(0)
+
+#else
+
+#include <setjmp.h>
+#include <signal.h>
+
+sigjmp_buf *exc_jmp_buf[MAX_THREADS];
+
+static void exception_handler(int sig) {
+  if (sig == SIGBUS) {
+    int tidx = yr_get_tidx();
+    if (tidx != -1 && exc_jmp_buf[tidx] != NULL) {
+      siglongjmp(*exc_jmp_buf[tidx], 1);
+    }
+    /* We should not reach this point. */
+    abort();
+  }
+}
+
+typedef struct sigaction sa;
+
+#define YR_TRYCATCH(_try_clause_,_catch_clause_)                \
+  do {                                                          \
+    struct sigaction oldact;                                    \
+    struct sigaction act;                                       \
+    sigset_t oldmask;                                           \
+    act.sa_handler = exception_handler;                         \
+    act.sa_flags = 0; /* SA_ONSTACK? */                         \
+    sigemptyset(&act.sa_mask);                                  \
+    pthread_sigmask(SIG_SETMASK, &act.sa_mask, &oldmask);       \
+    sigaction(SIGBUS, &act, &oldact);                           \
+    int tidx = yr_get_tidx();                                   \
+    if (tidx == -1) {                                           \
+      abort();                                                  \
+    }                                                           \
+    sigjmp_buf jb;                                              \
+    exc_jmp_buf[tidx] = &jb;                                    \
+    if (sigsetjmp(jb, 1) == 0)                                  \
+      { _try_clause_ }                                          \
+    else                                                        \
+      { _catch_clause_ }                                        \
+    exc_jmp_buf[tidx] = NULL;                                   \
+    sigaction(SIGBUS, &oldact, NULL);                           \
+    pthread_sigmask(SIG_SETMASK, &oldmask, NULL);               \
+  } while (0)
+
+#endif
+
+#endif /* _EXCEPTION_H_ */
diff --git a/libyara/rules.c b/libyara/rules.c
index 2bf421b..eae4b98 100644
--- a/libyara/rules.c
+++ b/libyara/rules.c
@@ -36,7 +36,7 @@ limitations under the License.
 #include <yara/scan.h>
 #include <yara/modules.h>
 
-
+#include "exception.h"
 
 void _yr_rules_lock(
     YR_RULES* rules)
@@ -400,23 +400,29 @@ YR_API int yr_rules_scan_mem_blocks(
   {
     if (context.entry_point == UNDEFINED)
     {
-      if (flags & SCAN_FLAGS_PROCESS_MEMORY)
-        context.entry_point = yr_get_entry_point_address(
-            block->data,
-            block->size,
-            block->base);
-      else
-        context.entry_point = yr_get_entry_point_offset(
-            block->data,
-            block->size);
+      YR_TRYCATCH({
+          if (flags & SCAN_FLAGS_PROCESS_MEMORY)
+            context.entry_point = yr_get_entry_point_address(
+                block->data,
+                block->size,
+                block->base);
+          else
+            context.entry_point = yr_get_entry_point_offset(
+                block->data,
+                block->size);
+        },{});
     }
 
-    result = _yr_rules_scan_mem_block(
-        rules,
-        block,
-        &context,
-        timeout,
-        start_time);
+    YR_TRYCATCH({
+        result = _yr_rules_scan_mem_block(
+            rules,
+            block,
+            &context,
+            timeout,
+            start_time);
+      },{
+        result = ERROR_COULD_NOT_MAP_FILE;
+      });
 
     if (result != ERROR_SUCCESS)
       goto _exit;
@@ -424,11 +430,15 @@ YR_API int yr_rules_scan_mem_blocks(
     block = block->next;
   }
 
-  result = yr_execute_code(
-      rules,
-      &context,
-      timeout,
-      start_time);
+  YR_TRYCATCH({
+      result = yr_execute_code(
+          rules,
+          &context,
+          timeout,
+          start_time);
+    },{
+      result = ERROR_COULD_NOT_MAP_FILE;
+    });
 
   if (result != ERROR_SUCCESS)
     goto _exit;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list