Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package yara for openSUSE:Factory checked in at 2022-08-23 14:29:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yara (Old) and /work/SRC/openSUSE:Factory/.yara.new.2083 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yara" Tue Aug 23 14:29:38 2022 rev:16 rq:998699 version:4.2.3 Changes: -------- --- /work/SRC/openSUSE:Factory/yara/yara.changes 2022-07-19 17:19:47.548401079 +0200 +++ /work/SRC/openSUSE:Factory/.yara.new.2083/yara.changes 2022-08-23 14:29:49.723635422 +0200 @@ -1,0 +2,9 @@ +Tue Aug 9 20:24:40 UTC 2022 - Dirk M??ller <[email protected]> + +- update to 4.2.3: + * BUGFIX: Fix security issue that can lead to arbitrary code execution + (b77e4f4, b77e4f4). Thanks to ANSSI - CERT-FR for the report. + * BUGFIX: Fix incorrect logic in expressions like <quantifier> of + <string_set> in (start..end (#1757). + +------------------------------------------------------------------- Old: ---- yara-4.2.2.tar.gz New: ---- yara-4.2.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yara.spec ++++++ --- /var/tmp/diff_new_pack.NB6S5c/_old 2022-08-23 14:29:52.267640741 +0200 +++ /var/tmp/diff_new_pack.NB6S5c/_new 2022-08-23 14:29:52.271640749 +0200 @@ -18,7 +18,7 @@ %global soname 9 Name: yara -Version: 4.2.2 +Version: 4.2.3 Release: 0 Summary: A malware identification and classification tool License: BSD-3-Clause ++++++ yara-4.2.2.tar.gz -> yara-4.2.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/bazel/yara.bzl new/yara-4.2.3/bazel/yara.bzl --- old/yara-4.2.2/bazel/yara.bzl 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/bazel/yara.bzl 2022-08-08 13:29:28.000000000 +0200 @@ -61,6 +61,7 @@ def yara_library( name, defines = [], + includes = [], modules = [], modules_srcs = [], deps = [], @@ -195,7 +196,7 @@ "libyara/include/yara/rules.h", ], copts = copts, - includes = [ + includes = includes + [ "libyara/modules", "libyara/include", "libyara", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/configure.ac new/yara-4.2.3/configure.ac --- old/yara-4.2.2/configure.ac 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/configure.ac 2022-08-08 13:29:28.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([yara], [4.2.2], [[email protected]]) +AC_INIT([yara], [4.2.3], [[email protected]]) AM_SILENT_RULES([yes]) AC_CONFIG_SRCDIR([cli/yara.c]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/libyara/exec.c new/yara-4.2.3/libyara/exec.c --- old/yara-4.2.2/libyara/exec.c 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/libyara/exec.c 2022-08-08 13:29:28.000000000 +0200 @@ -326,6 +326,22 @@ return ERROR_SUCCESS; } +// Global table that contains the "next" function for different types of +// iterators. The reason for using this table is to avoid storing pointers +// in the YARA's VM stack. Instead of the pointers we store an index within +// this table. +static YR_ITERATOR_NEXT_FUNC iter_next_func_table[] = { + iter_array_next, + iter_dict_next, + iter_int_range_next, + iter_int_enum_next, +}; + +#define ITER_NEXT_ARRAY 0 +#define ITER_NEXT_DICT 1 +#define ITER_NEXT_INT_RANGE 2 +#define ITER_NEXT_INT_ENUM 3 + int yr_execute_code(YR_SCAN_CONTEXT* context) { YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__); @@ -428,7 +444,7 @@ pop(r1); r2.it->array_it.array = r1.o; r2.it->array_it.index = 0; - r2.it->next = iter_array_next; + r2.it->next_func_idx = ITER_NEXT_ARRAY; push(r2); } @@ -449,7 +465,7 @@ pop(r1); r2.it->dict_it.dict = r1.o; r2.it->dict_it.index = 0; - r2.it->next = iter_dict_next; + r2.it->next_func_idx = ITER_NEXT_DICT; push(r2); } @@ -473,7 +489,7 @@ pop(r1); r3.it->int_range_it.next = r1.i; r3.it->int_range_it.last = r2.i; - r3.it->next = iter_int_range_next; + r3.it->next_func_idx = ITER_NEXT_INT_RANGE; push(r3); } @@ -499,7 +515,7 @@ { r3.it->int_enum_it.count = r1.i; r3.it->int_enum_it.next = 0; - r3.it->next = iter_int_enum_next; + r3.it->next_func_idx = ITER_NEXT_INT_ENUM; for (int64_t i = r1.i; i > 0; i--) { @@ -519,11 +535,22 @@ // Loads the iterator in r1, but leaves the iterator in the stack. pop(r1); push(r1); - // The iterator's next function is responsible for pushing the next - // item in the stack, and a boolean indicating if there are more items - // to retrieve. The boolean will be at the top of the stack after - // calling "next". - result = r1.it->next(r1.it, &stack); + + if (r1.it->next_func_idx < + sizeof(iter_next_func_table) / sizeof(YR_ITERATOR_NEXT_FUNC)) + { + // The iterator's next function is responsible for pushing the next + // item in the stack, and a boolean indicating if there are more items + // to retrieve. The boolean will be at the top of the stack after + // calling "next". + result = iter_next_func_table[r1.it->next_func_idx](r1.it, &stack); + } + else + { + // next_func_idx is outside the valid range, this should not happend. + result = ERROR_INTERNAL_FATAL_ERROR; + } + stop = (result != ERROR_SUCCESS); break; @@ -1388,10 +1415,24 @@ { YR_DEBUG_FPRINTF(2, stderr, "- case OP_OF: // %s()\n", __FUNCTION__); + // Quantifier is "all" if (is_undef(r2)) + { r1.i = found >= count ? 1 : 0; + } + // Quantifier is 0 or none. This is a special case in which we want + // exactly 0 strings matching. More information at: + // https://github.com/VirusTotal/yara/issues/1695 + else if (r2.i == 0) + { + r1.i = found == 0 ? 1 : 0; + } + // In all other cases the number of strings matching should be at + // least the amount specified by the quantifier. else + { r1.i = found >= r2.i ? 1 : 0; + } } else // OP_OF_PERCENT { @@ -1416,12 +1457,23 @@ found = 0; count = 0; - pop(r2); - pop(r1); - ensure_defined(r1); - ensure_defined(r2); - pop(r3); + pop(r2); // Offset range end + pop(r1); // Offset range start + pop(r3); // First string + + // If any of the range boundaries are undefined the result is also + // undefined, be we need to unwind the stack first. + if (is_undef(r1) || is_undef(r2)) + { + // Remove all the strings. + while (!is_undef(r3)) pop(r3); + // Remove the quantifier at the bottom of the stack. + pop(r3); + r1.i = YR_UNDEFINED; + push(r1); + break; + } while (!is_undef(r3)) { @@ -1432,6 +1484,7 @@ while (match != NULL) { + // String match within range start and range end? if (match->base + match->offset >= r1.i && match->base + match->offset <= r2.i) { @@ -1439,6 +1492,9 @@ break; } + // If current match is past range end, we can stop as matches + // are sortred by offset in increasing order, so all remaining + // matches are part the range end too. if (match->base + match->offset > r1.i) break; @@ -1449,11 +1505,26 @@ pop(r3); } - pop(r1); - if (is_undef(r1)) + pop(r2); // Quantifier X in expressions like "X of string_set in range" + + // Quantifier is "all". + if (is_undef(r2)) + { r1.i = found >= count ? 1 : 0; + } + // Quantifier is 0 or none. This is a special case in which we want + // exactly 0 strings matching. More information at: + // https://github.com/VirusTotal/yara/issues/1695 + else if (r2.i == 0) + { + r1.i = found == 0 ? 1 : 0; + } + // In all other cases the number of strings matching should be at least + // the amount specified by the quantifier. else - r1.i = found >= r1.i ? 1 : 0; + { + r1.i = found >= r2.i ? 1 : 0; + } push(r1); break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/libyara/include/yara/libyara.h new/yara-4.2.3/libyara/include/yara/libyara.h --- old/yara-4.2.2/libyara/include/yara/libyara.h 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/libyara/include/yara/libyara.h 2022-08-08 13:29:28.000000000 +0200 @@ -34,7 +34,7 @@ #define YR_MAJOR_VERSION 4 #define YR_MINOR_VERSION 2 -#define YR_MICRO_VERSION 2 +#define YR_MICRO_VERSION 3 #define version_str(s) _version_str(s) #define _version_str(s) #s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/libyara/include/yara/types.h new/yara-4.2.3/libyara/include/yara/types.h --- old/yara-4.2.2/libyara/include/yara/types.h 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/libyara/include/yara/types.h 2022-08-08 13:29:28.000000000 +0200 @@ -397,12 +397,21 @@ #pragma warning(disable : 4200) #endif +// The RE structure is embedded in the YARA's VM instruction flow, which +// means that its alignment is not guaranteed. For this reason the it must +// be a "packed" structure, in order to prevent alignment issues in platforms +// with strict alignment constraints. +#pragma pack(push) +#pragma pack(1) + struct RE { uint32_t flags; uint8_t code[0]; }; +#pragma pack(pop) + #ifdef _MSC_VER #pragma warning(pop) #endif @@ -979,7 +988,8 @@ struct YR_ITERATOR { - YR_ITERATOR_NEXT_FUNC next; + // Index of the next function within the iter_next_func_table global array. + int next_func_idx; union { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yara-4.2.2/tests/test-rules.c new/yara-4.2.3/tests/test-rules.c --- old/yara-4.2.2/tests/test-rules.c 2022-06-30 11:06:13.000000000 +0200 +++ new/yara-4.2.3/tests/test-rules.c 2022-08-08 13:29:28.000000000 +0200 @@ -631,6 +631,28 @@ }", "foobarbaz" TEXT_1024_BYTES); + // https://github.com/VirusTotal/yara/issues/1695 + assert_false_rule( + "rule test {\n\ + strings:\n\ + $a = \"AXS\"\n\ + $b = \"ERS\"\n\ + condition:\n\ + none of them in (0..10)\n\ + }", + "AXSERS" TEXT_1024_BYTES); + + // https://github.com/VirusTotal/yara/issues/1757 + assert_false_rule( + "rule test {\n\ + strings:\n\ + $a = \"foo\"\n\ + $b = \"foo\"\n\ + condition:\n\ + none of them in (0..1)\n\ + }", + "foo"); + // https://github.com/VirusTotal/yara/issues/1660 assert_false_rule( "rule test {\n\ @@ -1724,6 +1746,28 @@ }", "mississippi"); + // If one of the bounds can not be determined statically it isn't an error. + assert_true_rule( + "rule test { \ + strings: \ + $a = \"AXSERS\" \ + condition: \ + true or any of them in (0..filesize-100) \ + }", + TEXT_1024_BYTES); + + // Make sure that an undefined range boundary returns an undefined value, + // which translates to false. + assert_false_rule( + "import \"tests\" \ + rule test { \ + strings: \ + $a = \"missi\" \ + condition: \ + any of them in (0..tests.undefined.i) \ + }", + "mississippi"); + YR_DEBUG_FPRINTF(1, stderr, "} // %s()\n", __FUNCTION__); } @@ -1952,6 +1996,16 @@ }", NULL); + // Test case for https://github.com/VirusTotal/yara/issues/1729 + assert_true_rule( + "rule test { \ + strings: \ + $a = \"abcde\" \ + condition: \ + for any n in (1..10) : ( n of ($a*) ) \ + }", + "abcde"); + YR_DEBUG_FPRINTF(1, stderr, "} // %s()\n", __FUNCTION__); }
