Skip to content

Commit db22ffd

Browse files
committed
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.
1 parent 040db95 commit db22ffd

File tree

2 files changed

+127
-21
lines changed

2 files changed

+127
-21
lines changed

libyara/exception.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#ifndef _EXCEPTION_H_
2+
#define _EXCEPTION_H_
3+
4+
#if _WIN32
5+
6+
#include <windows.h>
7+
#include <setjmp.h>
8+
9+
#define YR_EXCEPT(_try_clause_, _catch_clause_) \
10+
_try_clause_
11+
12+
jmp_buf *exc_jmp_buf[MAX_THREADS];
13+
14+
static LONG CALLBACK exception_handler(
15+
PEXCEPTION_POINTERS ExceptionInfo)
16+
{
17+
switch(ExceptionInfo->ExceptionRecord->ExceptionCode) {
18+
case EXCEPTION_IN_PAGE_ERROR:
19+
case EXCEPTION_ACCESS_VIOLATION:
20+
break;
21+
default:
22+
return EXCEPTION_CONTINUE_SEARCH;
23+
}
24+
int tidx = yr_get_tidx();
25+
if (tidx != -1 && exc_jmp_buf[tidx] != NULL) {
26+
longjmp(*exc_jmp_buf[tidx], 1);
27+
}
28+
/* We should not reach this point. */
29+
abort();
30+
}
31+
32+
#define YR_TRYCATCH(_try_clause_,_catch_clause_) \
33+
do { \
34+
HANDLE exh = AddVectoredExceptionHandler(1, exception_handler); \
35+
int tidx = yr_get_tidx(); \
36+
if (tidx == -1) { \
37+
abort(); \
38+
} \
39+
jmp_buf jb; \
40+
exc_jmp_buf[tidx] = &jb; \
41+
if (setjmp(jb) == 0) \
42+
{ _try_clause_ } \
43+
else \
44+
{ _catch_clause_ } \
45+
exc_jmp_buf[tidx] = NULL; \
46+
RemoveVectoredExceptionHandler(exh); \
47+
} while(0)
48+
49+
#else
50+
51+
#include <setjmp.h>
52+
#include <signal.h>
53+
54+
sigjmp_buf *exc_jmp_buf[MAX_THREADS];
55+
56+
static void exception_handler(int sig) {
57+
if (sig == SIGBUS) {
58+
int tidx = yr_get_tidx();
59+
if (tidx != -1 && exc_jmp_buf[tidx] != NULL) {
60+
siglongjmp(*exc_jmp_buf[tidx], 1);
61+
}
62+
/* We should not reach this point. */
63+
abort();
64+
}
65+
}
66+
67+
typedef struct sigaction sa;
68+
69+
#define YR_TRYCATCH(_try_clause_,_catch_clause_) \
70+
do { \
71+
struct sigaction oldact; \
72+
struct sigaction act; \
73+
sigset_t oldmask; \
74+
act.sa_handler = exception_handler; \
75+
act.sa_flags = 0; /* SA_ONSTACK? */ \
76+
sigemptyset(&act.sa_mask); \
77+
pthread_sigmask(SIG_SETMASK, &act.sa_mask, &oldmask); \
78+
sigaction(SIGBUS, &act, &oldact); \
79+
int tidx = yr_get_tidx(); \
80+
if (tidx == -1) { \
81+
abort(); \
82+
} \
83+
sigjmp_buf jb; \
84+
exc_jmp_buf[tidx] = &jb; \
85+
if (sigsetjmp(jb, 1) == 0) \
86+
{ _try_clause_ } \
87+
else \
88+
{ _catch_clause_ } \
89+
exc_jmp_buf[tidx] = NULL; \
90+
sigaction(SIGBUS, &oldact, NULL); \
91+
pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \
92+
} while (0)
93+
94+
#endif
95+
96+
#endif /* _EXCEPTION_H_ */

libyara/rules.c

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ limitations under the License.
3636
#include <yara/scan.h>
3737
#include <yara/modules.h>
3838

39-
39+
#include "exception.h"
4040

4141
void _yr_rules_lock(
4242
YR_RULES* rules)
@@ -400,35 +400,45 @@ YR_API int yr_rules_scan_mem_blocks(
400400
{
401401
if (context.entry_point == UNDEFINED)
402402
{
403-
if (flags & SCAN_FLAGS_PROCESS_MEMORY)
404-
context.entry_point = yr_get_entry_point_address(
405-
block->data,
406-
block->size,
407-
block->base);
408-
else
409-
context.entry_point = yr_get_entry_point_offset(
410-
block->data,
411-
block->size);
403+
YR_TRYCATCH({
404+
if (flags & SCAN_FLAGS_PROCESS_MEMORY)
405+
context.entry_point = yr_get_entry_point_address(
406+
block->data,
407+
block->size,
408+
block->base);
409+
else
410+
context.entry_point = yr_get_entry_point_offset(
411+
block->data,
412+
block->size);
413+
},{});
412414
}
413415

414-
result = _yr_rules_scan_mem_block(
415-
rules,
416-
block,
417-
&context,
418-
timeout,
419-
start_time);
416+
YR_TRYCATCH({
417+
result = _yr_rules_scan_mem_block(
418+
rules,
419+
block,
420+
&context,
421+
timeout,
422+
start_time);
423+
},{
424+
result = ERROR_COULD_NOT_MAP_FILE;
425+
});
420426

421427
if (result != ERROR_SUCCESS)
422428
goto _exit;
423429

424430
block = block->next;
425431
}
426432

427-
result = yr_execute_code(
428-
rules,
429-
&context,
430-
timeout,
431-
start_time);
433+
YR_TRYCATCH({
434+
result = yr_execute_code(
435+
rules,
436+
&context,
437+
timeout,
438+
start_time);
439+
},{
440+
result = ERROR_COULD_NOT_MAP_FILE;
441+
});
432442

433443
if (result != ERROR_SUCCESS)
434444
goto _exit;

0 commit comments

Comments
 (0)