From 30f86480428253e35ef0f509328c7b6831d21735 Mon Sep 17 00:00:00 2001 From: yixiangzhike Date: Tue, 18 Oct 2022 09:47:24 +0800 Subject: [PATCH] switch from PCRE to PCRE2 Signed-off-by: yixiangzhike --- aide.spec | 16 +- ...Switch-from-PCRE-to-PCRE2-closes-116.patch | 376 ++++++++++++++++++ 2 files changed, 390 insertions(+), 2 deletions(-) create mode 100644 backport-Switch-from-PCRE-to-PCRE2-closes-116.patch diff --git a/aide.spec b/aide.spec index f166478..3dc2be7 100644 --- a/aide.spec +++ b/aide.spec @@ -1,6 +1,6 @@ Name: aide Version: 0.17.3 -Release: 5 +Release: 6 Summary: Advanced Intrusion Detection Environment License: GPLv2+ URL: http://sourceforge.net/projects/aide @@ -8,13 +8,16 @@ Source0: http://github.com/aide/aide/releases/download/v%{version}/%{name}-%{ Source1: aide.conf Source2: aide.logrotate -BuildRequires: gcc make bison flex pcre-devel libgpg-error-devel libgcrypt-devel zlib-devel libcurl-devel +BuildRequires: gcc make bison flex pcre2-devel libgpg-error-devel libgcrypt-devel zlib-devel libcurl-devel BuildRequires: libacl-devel libselinux-devel libattr-devel e2fsprogs-devel audit-libs-devel +# command autoreconf needs autoconf and automake +BuildRequires: autoconf automake Patch0: Add-sm3-algorithm-for-aide.patch Patch1: backport-CVE-2021-45417-Precalculate-buffer-size-in-base64-functions.patch Patch2: backport-Handle-malformed-database-lines.patch Patch3: backport-Fix-handling-of-duplicate-database-entries.patch +Patch4: backport-Switch-from-PCRE-to-PCRE2-closes-116.patch %description AIDE (Advanced Intrusion Detection Environment, [eyd]) is a file and directory integrity checker. @@ -27,6 +30,9 @@ Once this database is initialized it can be used to verify the integrity of the %autosetup -n %{name}-%{version} -p1 %build +# add command autoreconf to regenerate configure file +# because, the patch Switch-from-PCRE-to-PCRE2 changed configure.ac file +autoreconf -ivf %configure --disable-static --with-config_file=%{_sysconfdir}/aide.conf --with-gcrypt --with-zlib \ --with-curl --with-posix-acl --with-selinux --with-xattr --with-e2fsattrs --with-audit make %{?_smp_mflags} @@ -62,6 +68,12 @@ mkdir -p -m0700 %{buildroot}%{_localstatedir}/lib/aide %{_mandir}/*/* %changelog +* Tue Oct 18 2022 yixiangzhike - 0.17.3-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: switch from PCRE to PCRE2 + * Tue Feb 22 2022 yixiangzhike - 0.17.3-5 - Type:bugfix - ID:NA diff --git a/backport-Switch-from-PCRE-to-PCRE2-closes-116.patch b/backport-Switch-from-PCRE-to-PCRE2-closes-116.patch new file mode 100644 index 0000000..3a42fcf --- /dev/null +++ b/backport-Switch-from-PCRE-to-PCRE2-closes-116.patch @@ -0,0 +1,376 @@ +From 367545d8e27aec9d0d407bafd8da81f5df42ce31 Mon Sep 17 00:00:00 2001 +From: Hannes von Haugwitz +Date: Wed, 1 Dec 2021 21:17:44 +0100 +Subject: [PATCH] Switch from PCRE to PCRE2 (closes: #116) + +--- + Makefile.am | 4 ++-- + README | 2 +- + configure.ac | 13 +++++-------- + include/db_config.h | 6 ++++-- + include/gen_list.h | 3 ++- + include/rx_rule.h | 6 ++++-- + include/seltree.h | 2 +- + src/aide.c | 26 ++++++++++++++++++++++---- + src/commandconf.c | 6 +----- + src/conf_eval.c | 25 +++++++++++++++++-------- + src/gen_list.c | 10 +++++----- + src/seltree.c | 32 +++++++++++++++++++++++++------- + 12 files changed, 89 insertions(+), 46 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 4744ec4..21a552e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -62,7 +62,7 @@ if USE_CURL + aide_SOURCES += include/fopen.h src/fopen.c + endif + +-aide_LDADD = -lm @PCRELIB@ @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ @E2FSATTRSLIB@ @ELFLIB@ @CAPLIB@ ${CURL_LIBS} ++aide_LDADD = -lm ${PCRE2_LIBS} @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ @E2FSATTRSLIB@ @ELFLIB@ @CAPLIB@ ${CURL_LIBS} + + if HAVE_CHECK + TESTS = check_aide +@@ -71,7 +71,7 @@ check_aide_SOURCES = tests/check_aide.c tests/check_aide.h \ + tests/check_attributes.c src/attributes.c \ + src/log.c src/util.c + check_aide_CFLAGS = -I$(top_srcdir)/include $(CHECK_CFLAGS) +-check_aide_LDADD = -lm @PCRELIB@ @CRYPTLIB@ $(CHECK_LIBS) ++check_aide_LDADD = -lm ${PCRE2_LIBS} @CRYPTLIB@ $(CHECK_LIBS) + endif # HAVE_CHECK + + AM_CFLAGS = @AIDE_DEFS@ -W -Wall -g +diff --git a/README b/README +index 079d4b2..3526065 100644 +--- a/README ++++ b/README +@@ -117,7 +117,7 @@ + o GNU yacc (bison). + o GNU make. + o pkg-config +- o PCRE library ++ o PCRE2 library + o Mhash (optional, but highly recommended). Mhash is currently + available from http://mhash.sourceforge.net/. A static version of + libmhash needs to be build using the --enable-static=yes +diff --git a/configure.ac b/configure.ac +index ae9e6b9..a741a1b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -328,15 +328,12 @@ fi + + AC_CHECK_HEADERS(syslog.h inttypes.h fcntl.h ctype.h) + +-PCRELIB="-lpcre" +-if test "$aide_static_choice" == "yes"; then +- PCRELIB="$PCRELIB -pthread" ++if test "$aide_static_choice" == "yes"; then ++ PKG_CHECK_MODULES_STATIC(PCRE2, [libpcre2-8], , [AC_MSG_RESULT([libpcre2-8 not found by pkg-config - Try to add directory containing libpcre2-8.pc to PKG_CONFIG_PATH environment variable])]) ++else ++ PKG_CHECK_MODULES(PCRE2, [libpcre2-8], , [AC_MSG_RESULT([libpcre2-8 not found by pkg-config - Try to add directory containing libpcre2-8.pc to PKG_CONFIG_PATH environment variable])]) + fi +-AC_CHECK_LIB(pcre, pcre_exec, [ +- compoptionstring="${compoptionstring}WITH_PCRE\\n" +- ], [AC_MSG_ERROR([You don't have pcre library properly installed.])] +- ) +-AC_SUBST(PCRELIB) ++compoptionstring="${compoptionstring}WITH_PCRE2\\n" + + AC_ARG_WITH([locale], + [AC_HELP_STRING([--with-locale], +diff --git a/include/db_config.h b/include/db_config.h +index dbe0138..49fa384 100644 +--- a/include/db_config.h ++++ b/include/db_config.h +@@ -28,7 +28,8 @@ + #include "types.h" + #include + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + + #define E2O(n) (1< ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + #include "seltree.h" + #include "list.h" + #include +diff --git a/include/rx_rule.h b/include/rx_rule.h +index fa8bdd3..196a5b7 100644 +--- a/include/rx_rule.h ++++ b/include/rx_rule.h +@@ -25,7 +25,8 @@ + #include "attributes.h" + #include "seltree_struct.h" + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + + #define RESTRICTION_TYPE unsigned int + #define FT_REG (1U<<0) /* file */ +@@ -41,7 +42,8 @@ + + typedef struct rx_rule { + char* rx; /* Regular expression in text form */ +- pcre* crx; /* Compiled regexp */ ++ pcre2_code* crx; /* Compiled regexp */ ++ pcre2_match_data *md; + DB_ATTR_TYPE attr; /* Which attributes to save */ + seltree *node; + char *config_filename; +diff --git a/include/seltree.h b/include/seltree.h +index c4e6f05..61f9a8c 100644 +--- a/include/seltree.h ++++ b/include/seltree.h +@@ -32,7 +32,7 @@ seltree* new_seltree_node(seltree*, char*, int, rx_rule*); + + seltree* get_seltree_node(seltree* ,char*); + +-rx_rule * add_rx_to_tree(char *, RESTRICTION_TYPE, int, seltree *, const char **, int *); ++rx_rule * add_rx_to_tree(char *, RESTRICTION_TYPE, int, seltree *, int, char *, char *); + + int check_seltree(seltree *, char *, RESTRICTION_TYPE, rx_rule* *); + +diff --git a/src/aide.c b/src/aide.c +index 12ecfe1..741e1cd 100644 +--- a/src/aide.c ++++ b/src/aide.c +@@ -283,13 +283,31 @@ static void read_param(int argc,char**argv) + break; + } + case 'l': { +- const char* pcre_error; +- int pcre_erroffset; ++ int pcre2_errorcode; ++ PCRE2_SIZE pcre2_erroffset; + conf->limit=checked_malloc(strlen(optarg)+1); + strcpy(conf->limit,optarg); +- if((conf->limit_crx=pcre_compile(conf->limit, PCRE_ANCHORED, &pcre_error, &pcre_erroffset, NULL)) == NULL) { +- INVALID_ARGUMENT("--limit", error in regular expression '%s' at %i: %s, conf->limit, pcre_erroffset, pcre_error) ++ if((conf->limit_crx=pcre2_compile((PCRE2_SPTR) conf->limit, PCRE2_ZERO_TERMINATED, PCRE2_UTF|PCRE2_ANCHORED, &pcre2_errorcode, &pcre2_erroffset, NULL)) == NULL) { ++ PCRE2_UCHAR pcre2_error[128]; ++ pcre2_get_error_message(pcre2_errorcode, pcre2_error, 128); ++ INVALID_ARGUMENT("--limit", error in regular expression '%s' at %zu: %s, conf->limit, pcre2_erroffset, pcre2_error) ++ ++ } ++ conf->limit_md = pcre2_match_data_create_from_pattern(conf->limit_crx, NULL); ++ if (conf->limit_md == NULL) { ++ log_msg(LOG_LEVEL_ERROR, "pcre2_match_data_create_from_pattern: failed to allocate memory"); ++ exit(EXIT_FAILURE); ++ } ++ ++ int pcre2_jit = pcre2_jit_compile(conf->limit_crx, PCRE2_JIT_PARTIAL_SOFT); ++ if (pcre2_jit < 0) { ++ PCRE2_UCHAR pcre2_error[128]; ++ pcre2_get_error_message(pcre2_jit, pcre2_error, 128); ++ log_msg(LOG_LEVEL_NOTICE, "JIT compilation for limit '%s' failed: %s (fall back to interpreted matching)", conf->limit, pcre2_error); ++ } else { ++ log_msg(LOG_LEVEL_DEBUG, "JIT compilation for limit '%s' successful", conf->limit); + } ++ + log_msg(LOG_LEVEL_INFO,_("(--limit): set limit to '%s'"), conf->limit); + break; + } +diff --git a/src/commandconf.c b/src/commandconf.c +index edec4f9..a3b0e27 100644 +--- a/src/commandconf.c ++++ b/src/commandconf.c +@@ -307,11 +307,7 @@ bool add_rx_rule_to_tree(char* rx, RESTRICTION_TYPE restriction, DB_ATTR_TYPE at + char *attr_str = NULL; + char *rs_str = NULL; + +- const char* rule_error; +- int rule_erroffset; +- +- if ((r = add_rx_to_tree(rx, restriction, type, tree, &rule_error, &rule_erroffset)) == NULL) { +- log_msg(LOG_LEVEL_ERROR, "%s:%d:%i: error in rule '%s': %s (line: '%s')", filename, linenumber, rule_erroffset, rx, rule_error, linebuf); ++ if ((r = add_rx_to_tree(rx, restriction, type, tree, linenumber, filename, linebuf)) == NULL) { + retval = false; + }else { + r->config_linenumber = linenumber; +diff --git a/src/conf_eval.c b/src/conf_eval.c +index 460e530..7d9b182 100644 +--- a/src/conf_eval.c ++++ b/src/conf_eval.c +@@ -512,14 +512,21 @@ static void include_directory(const char* dir, const char* rx, bool execute, int + struct dirent **namelist; + int n; + +- const char* pcre_error; +- int pcre_erroffset; +- pcre* crx; +- +- if((crx = pcre_compile(rx, PCRE_UTF8, &pcre_error, &pcre_erroffset, NULL)) == NULL) { +- LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, '%s': error in regular expression '%s' at %i: %s, execute?"@@x_include":"@@include", rx, pcre_erroffset, pcre_error) ++ int pcre2_errorcode; ++ PCRE2_SIZE pcre2_erroffset; ++ pcre2_code* crx; ++ ++ if((crx = pcre2_compile((PCRE2_SPTR) rx, PCRE2_ZERO_TERMINATED, PCRE2_UTF, &pcre2_errorcode, &pcre2_erroffset, NULL)) == NULL) { ++ PCRE2_UCHAR pcre2_error[128]; ++ pcre2_get_error_message(pcre2_errorcode, pcre2_error, 128); ++ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, '%s': error in regular expression '%s' at %i: %s, execute?"@@x_include":"@@include", rx, pcre2_erroffset, pcre2_error) + exit(INVALID_CONFIGURELINE_ERROR); + } ++ pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(crx, NULL); ++ if (match_data == NULL) { ++ log_msg(LOG_LEVEL_ERROR, "pcre2_match_data_create_from_pattern: failed to allocate memory"); ++ exit(EXIT_FAILURE); ++ } + + struct stat fs; + +@@ -547,7 +554,8 @@ static void include_directory(const char* dir, const char* rx, bool execute, int + exit(INVALID_CONFIGURELINE_ERROR); + } + if (S_ISREG(fs.st_mode)) { +- if(pcre_exec(crx, NULL, namelist[i]->d_name, strlen(namelist[i]->d_name), 0, 0, NULL, 0) < 0) { ++ int match=pcre2_match(crx, (PCRE2_SPTR) namelist[i]->d_name, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL); ++ if(match < 0) { + log_msg(LOG_LEVEL_DEBUG,"%s: skip '%s' (reason: file name does not match regex '%s')", dir, namelist[i]->d_name, rx); + } else { + int exec = execute && S_IXUSR&fs.st_mode; +@@ -565,7 +573,8 @@ static void include_directory(const char* dir, const char* rx, bool execute, int + free(namelist[i]); + } + free(namelist); +- free(crx); ++ pcre2_match_data_free(match_data); ++ pcre2_code_free(crx); + } + + static void eval_include_statement(include_statement statement, int include_depth, int linenumber, char *filename, char* linebuf) { +diff --git a/src/gen_list.c b/src/gen_list.c +index 98b437c..9c3aed5 100644 +--- a/src/gen_list.c ++++ b/src/gen_list.c +@@ -32,7 +32,8 @@ + #include + #include + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + + #include "attributes.h" + #include "list.h" +@@ -488,13 +489,12 @@ static void add_file_to_tree(seltree* tree,db_line* file,int db) + int check_rxtree(char* filename,seltree* tree, rx_rule* *rule, RESTRICTION_TYPE file_type, bool dry_run) + { + log_msg(LOG_LEVEL_RULE, "\u252c process '%s' (filetype: %c)", filename, get_restriction_char(file_type)); +- int retval=0; + + if(conf->limit!=NULL) { +- retval=pcre_exec(conf->limit_crx, NULL, filename, strlen(filename), 0, PCRE_PARTIAL_SOFT, NULL, 0); +- if (retval >= 0) { ++ int match=pcre2_match(conf->limit_crx, (PCRE2_SPTR) filename, PCRE2_ZERO_TERMINATED, 0, PCRE2_PARTIAL_SOFT, conf->limit_md, NULL); ++ if (match >= 0) { + log_msg(LOG_LEVEL_DEBUG, "\u2502 '%s' does match limit '%s'", filename, conf->limit); +- } else if (retval == PCRE_ERROR_PARTIAL) { ++ } else if (match == PCRE2_ERROR_PARTIAL) { + if(file_type&FT_DIR && get_seltree_node(tree,filename)==NULL){ + seltree* node = new_seltree_node(tree,filename,0,NULL); + log_msg(LOG_LEVEL_DEBUG, "added new node '%s' (%p) for '%s' (reason: partial limit match)", node->path, node, filename); +diff --git a/src/seltree.c b/src/seltree.c +index 7819b06..bc8b371 100644 +--- a/src/seltree.c ++++ b/src/seltree.c +@@ -260,7 +260,7 @@ seltree *init_tree() { + return node; + } + +-rx_rule * add_rx_to_tree(char * rx, RESTRICTION_TYPE restriction, int rule_type, seltree *tree, const char **rule_error, int *rule_erroffset) { ++rx_rule * add_rx_to_tree(char * rx, RESTRICTION_TYPE restriction, int rule_type, seltree *tree, int linenumber, char* filename, char* linebuf) { + rx_rule* r = NULL; + seltree *curnode = NULL; + char *rxtok = NULL; +@@ -275,17 +275,36 @@ rx_rule * add_rx_to_tree(char * rx, RESTRICTION_TYPE restriction, int rule_type, + r->config_linenumber = -1; + r->attr = 0; + +- if((r->crx=pcre_compile(r->rx, PCRE_ANCHORED|PCRE_UTF8, rule_error, rule_erroffset, NULL)) == NULL) { ++ int pcre2_errorcode; ++ PCRE2_SIZE pcre2_erroffset; ++ ++ if((r->crx=pcre2_compile((PCRE2_SPTR) r->rx, PCRE2_ZERO_TERMINATED, PCRE2_UTF|PCRE2_ANCHORED, &pcre2_errorcode, &pcre2_erroffset, NULL)) == NULL) { ++ PCRE2_UCHAR pcre2_error[128]; ++ pcre2_get_error_message(pcre2_errorcode, pcre2_error, 128); ++ log_msg(LOG_LEVEL_ERROR, "%s:%d:%i: error in rule '%s': %s (line: '%s')", filename, linenumber, pcre2_erroffset, rx, pcre2_error, linebuf); + free(r); + return NULL; + } else { ++ r->md = pcre2_match_data_create_from_pattern(r->crx, NULL); ++ if (r->md == NULL) { ++ log_msg(LOG_LEVEL_ERROR, "pcre2_match_data_create_from_pattern: failed to allocate memory"); ++ exit(EXIT_FAILURE); ++ } ++ int pcre2_jit = pcre2_jit_compile(r->crx, PCRE2_JIT_PARTIAL_SOFT); ++ if (pcre2_jit < 0) { ++ PCRE2_UCHAR pcre2_error[128]; ++ pcre2_get_error_message(pcre2_jit, pcre2_error, 128); ++ log_msg(LOG_LEVEL_NOTICE, "JIT compilation for regex '%s' failed: %s (fall back to interpreted matching)", r->rx, pcre2_error); ++ } else { ++ log_msg(LOG_LEVEL_DEBUG, "JIT compilation for reges '%s' successful", r->rx); ++ } ++ + rxtok=strrxtok(r->rx); + curnode=get_seltree_node(tree,rxtok); + + for(size_t i=1;i < strlen(rxtok); ++i){ + if (rxtok[i] == '/' && rxtok[i-1] == '/') { +- *rule_error = "invalid double slash" ; +- *rule_erroffset = i; ++ log_msg(LOG_LEVEL_ERROR, "%s:%d:1: error in rule '%s': invalid double slash (line: '%s')", filename, linenumber, rx, linebuf); + free(r); + return NULL; + } +@@ -323,14 +342,13 @@ static int check_list_for_match(list* rxrlist,char* text, rx_rule* *rule, RESTRI + list* r=NULL; + int retval=NO_RULE_MATCH; + int pcre_retval; +- pcre_extra *pcre_extra = NULL; + char *rs_str = NULL; + for(r=rxrlist;r;r=r->next){ + rx_rule *rx = (rx_rule*)r->data; + + if (!(unrestricted_only && rx->restriction)) { + +- pcre_retval=pcre_exec((pcre*)rx->crx, pcre_extra, text, strlen(text), 0, PCRE_PARTIAL_SOFT, NULL, 0); ++ pcre_retval = pcre2_match(rx->crx, (PCRE2_SPTR) text, PCRE2_ZERO_TERMINATED, 0, PCRE2_PARTIAL_SOFT, rx->md, NULL); + if (pcre_retval >= 0) { + if (!rx->restriction || file_type&rx->restriction) { + *rule = rx; +@@ -343,7 +361,7 @@ static int check_list_for_match(list* rxrlist,char* text, rx_rule* *rule, RESTRI + free(rs_str); + retval=PARTIAL_RULE_MATCH; + } +- } else if (pcre_retval == PCRE_ERROR_PARTIAL) { ++ } else if (pcre_retval == PCRE2_ERROR_PARTIAL) { + LOG_MATCH(LOG_LEVEL_RULE, "\u2502", partially matches regex '%s', rx->rx) + retval=PARTIAL_RULE_MATCH; + } else { +-- +1.8.3.1 + -- Gitee