[Forensics-changes] [yara] 57/192: Don't unmask signals when setting up exception handler (Unix) (#546)

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:31:46 UTC 2017


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

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

commit 8b2b6b8f82b8a8a8830bae122474b39ac2814fc6
Author: Hilko Bengen <hillu at users.noreply.github.com>
Date:   Mon Oct 31 09:40:38 2016 +0100

    Don't unmask signals when setting up exception handler (Unix) (#546)
    
    * YR_TRYCATCH: Remove duplicate initialization of oldmask
    
    * Add test for handling exceptions
    
    With
    
        #define YR_TRYCATCH(_try_clause_, _catch_clause_) {_try_clause_}
    
    this will cause a bus error on Linux -- as it should.
    
    * tests: Add assert_*_rule_blob_size, make count_matches usable from test code
    
    * test-exception: Block and send SIGUSR1 before 2nd yr_rules_scan_mem call
    
    This seems to reproduce something similar to the symptom described in
    
    $ ./test-exception
    Scanning for "aaaa"...
    err = 4, matches = 0
    Sending blocked SIGUSR1 to ourselves...
    Scanning for {00 00 00 00}...
    User defined signal 1
    
    * exception (UNIX): Remove unneeded pthread_sigmask() calls
    
    sigsetjmp() already saves the signal mask for us.
    
    Also, setting the signal mask using the (empty) act.sa_mask was wrong
    and led to the behavior described in #544.
    
    We still want delivery of all signals to be blocked during execution of
    the signal handler.
    
    * Document test-exception
---
 Makefile.am            |   4 +-
 libyara/exception.h    |   7 +---
 tests/test-exception.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/util.c           |   2 +-
 tests/util.h           |  20 +++++++--
 5 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 8c1652a..8f5ab59 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,7 @@ yarac_SOURCES = args.c args.h yarac.c
 yarac_LDADD = libyara/.libs/libyara.a
 
 TESTS = $(check_PROGRAMS)
-check_PROGRAMS = test-alignment test-rules test-pe test-elf
+check_PROGRAMS = test-alignment test-rules test-pe test-elf test-exception
 test_alignment_SOURCES = tests/test-alignment.c
 test_rules_SOURCES = tests/test-rules.c tests/util.c
 test_rules_LDADD = libyara/.libs/libyara.a
@@ -23,6 +23,8 @@ test_pe_SOURCES = tests/test-pe.c tests/util.c
 test_pe_LDADD = libyara/.libs/libyara.a
 test_elf_SOURCES = tests/test-elf.c tests/util.c
 test_elf_LDADD = libyara/.libs/libyara.a
+test_exception_SOURCES = tests/test-exception.c tests/util.c
+test_exception_LDADD = libyara/.libs/libyara.a
 
 # man pages
 man1_MANS = yara.man yarac.man
diff --git a/libyara/exception.h b/libyara/exception.h
index 436d006..c70ae63 100644
--- a/libyara/exception.h
+++ b/libyara/exception.h
@@ -99,13 +99,9 @@ typedef struct sigaction sa;
   {                                                             \
     struct sigaction oldact;                                    \
     struct sigaction act;                                       \
-    sigset_t oldmask;                                           \
     act.sa_handler = exception_handler;                         \
     act.sa_flags = 0; /* SA_ONSTACK? */                         \
-    sigemptyset(&oldmask);                                      \
-    sigemptyset(&act.sa_mask);                                  \
-    sigemptyset(&oldmask);                                      \
-    pthread_sigmask(SIG_SETMASK, &act.sa_mask, &oldmask);       \
+    sigfillset(&act.sa_mask);                                   \
     sigaction(SIGBUS, &act, &oldact);                           \
     int tidx = yr_get_tidx();                                   \
     assert(tidx != -1);                                         \
@@ -117,7 +113,6 @@ typedef struct sigaction sa;
       { _catch_clause_ }                                        \
     exc_jmp_buf[tidx] = NULL;                                   \
     sigaction(SIGBUS, &oldact, NULL);                           \
-    pthread_sigmask(SIG_SETMASK, &oldmask, NULL);               \
   } while (0)
 
 #endif
diff --git a/tests/test-exception.c b/tests/test-exception.c
new file mode 100644
index 0000000..19dc911
--- /dev/null
+++ b/tests/test-exception.c
@@ -0,0 +1,108 @@
+/*
+Copyright (c) 2016. The YARA Authors. All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include <yara.h>
+#include "util.h"
+
+int main(int argc, char **argv)
+{
+  char* filename = strdup("yara-testblob.XXXXXX");
+  int fd = mkstemp(filename);
+  char wbuf[4096];
+  int i;
+
+  if (fd <= 0)
+  {
+    perror("Create temp file");
+    return 77;
+  }
+  unlink(filename);
+
+  memset(wbuf, 'a', sizeof(wbuf));
+  for (i=0; i<=3; i++)
+    write(fd, wbuf, sizeof(wbuf));
+
+  uint8_t* mapped_region = mmap(NULL, 4*sizeof(wbuf), PROT_READ, MAP_SHARED, fd, 0);
+  ftruncate(fd, 2*sizeof(wbuf));
+  /*
+    mapped_region is now only partially backed by the open file
+    referred to by fd. Accessing the memory beyond
+
+        mapped_region + 2*sizeof(wbuf)
+
+    causes SIGBUS to be raised.
+  */
+
+  yr_initialize();
+
+  YR_RULES* rules_a = compile_rule("rule test { strings: $a = \"aaaa\" condition: all of them }");
+  YR_RULES* rules_0 = compile_rule("rule test { strings: $a = { 00 00 00 00 } condition: all of them }");
+
+  puts("Scanning for \"aaaa\"...");
+  int matches = 0;
+
+  /*
+    If YR_TRYCATCH is redefined like this
+
+        #define YR_TRYCATCH(_try_clause_,_catch_clause_) {_try_clause_}
+
+    yr_rules_scan_mem() will terminate the process.
+  */
+  int rc = yr_rules_scan_mem(rules_a, mapped_region, 4*sizeof(wbuf), 0, count_matches, &matches, 0);
+  printf("err = %d, matches = %d\n", rc, matches);
+  if (rc == ERROR_SUCCESS || matches != 0)
+    return 1;
+
+  puts("Sending blocked SIGUSR1 to ourselves...");
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set, SIGUSR1);
+  sigprocmask(SIG_BLOCK, &set, NULL);
+  kill(getpid(), SIGUSR1);
+
+  puts("Scanning for {00 00 00 00}...");
+  matches = 0;
+
+  /*
+    This tests that SIGUSR1 is not delivered when setting up SIGBUS
+    signal handling -- or during SIGBUS signal handling
+  */
+  rc = yr_rules_scan_mem(rules_0, mapped_region, 4*sizeof(wbuf), 0, count_matches, &matches, 0);
+  printf("err = %d, matches = %d\n", rc, matches);
+  if (rc == ERROR_SUCCESS || matches != 0)
+    return 1;
+
+  return 0;
+}
diff --git a/tests/util.c b/tests/util.c
index 5597c98..59105dd 100644
--- a/tests/util.c
+++ b/tests/util.c
@@ -82,7 +82,7 @@ _exit:
 }
 
 
-static int count_matches(
+int count_matches(
     int message,
     void* message_data,
     void* user_data)
diff --git a/tests/util.h b/tests/util.h
index 89b245b..835115f 100644
--- a/tests/util.h
+++ b/tests/util.h
@@ -36,6 +36,12 @@ YR_RULES* compile_rule(
     char* string);
 
 
+int count_matches(
+    int message,
+    void* message_data,
+    void* user_data);
+
+
 int matches_blob(
     char* rule,
     uint8_t* blob,
@@ -66,15 +72,18 @@ int read_file(
     }                                                                   \
   } while (0);
 
-#define assert_true_rule_blob(rule, blob)                               \
+#define assert_true_rule_blob_size(rule, blob, size)                    \
   do {                                                                  \
-    if (!matches_blob(rule, (uint8_t*) (blob), sizeof(blob))) {         \
+    if (!matches_blob(rule, (uint8_t*) (blob), size)) {                 \
       fprintf(stderr, "%s:%d: rule does not match (but should)\n",      \
               __FILE__, __LINE__ );                                     \
       exit(EXIT_FAILURE);                                               \
     }                                                                   \
   } while (0);
 
+#define assert_true_rule_blob(rule, blob)               \
+  assert_true_rule_blob_size(rule, blob, sizeof(blob))
+
 #define assert_true_rule_file(rule, filename)                           \
   do {                                                                  \
     char* buf;                                                          \
@@ -102,15 +111,18 @@ int read_file(
     }                                                                   \
   } while (0);
 
-#define assert_false_rule_blob(rule, blob)                              \
+#define assert_false_rule_blob_size(rule, blob, size)                   \
   do {                                                                  \
-    if (matches_blob(rule, (uint8_t*) (blob), sizeof(blob))) {          \
+    if (matches_blob(rule, (uint8_t*) (blob), size)) {                  \
       fprintf(stderr, "%s:%d: rule matches (but shouldn't)\n",          \
               __FILE__, __LINE__ );                                     \
       exit(EXIT_FAILURE);                                               \
     }                                                                   \
   } while (0);
 
+#define assert_false_rule_blob(rule, blob)              \
+  assert_false_rule_blob_size(rule, blob, sizeof(blob))
+
 #define assert_false_rule_file(rule, filename)                          \
   do {                                                                  \
     char* buf;                                                          \

-- 
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