Executables in src/ directory are built from source files in src/ and are linked to libauparse, with both src/auditd-config.c and auparse/auditd-config.c defining "free_config" function. It is known (although obscure) behaviour of shared libraries that symbol defined in binary itself overrides symbol in shared library; with static linkage it expectedly results in multiple definition error. This set of fixes explicitly marks libauparse versions of conflicting functions as weak to have behaviour coherent with dynamic linkage version -- definitions in src/ overriding definition in auparse/. Still, this architecture is very strange and confusing. diff -r -U5 audit-2.8.5-orig/auparse/auditd-config.c audit-2.8.5/auparse/auditd-config.c --- audit-2.8.5-orig/auparse/auditd-config.c 2019-03-01 20:19:13.000000000 +0000 +++ audit-2.8.5/auparse/auditd-config.c 2021-01-13 11:36:12.716226498 +0000 @@ -68,10 +68,11 @@ }; /* * Set everything to its default value */ +#pragma weak clear_config void clear_config(struct daemon_conf *config) { config->local_events = 1; config->qos = QOS_NON_BLOCKING; config->sender_uid = 0; @@ -322,10 +323,11 @@ if (config->log_file == NULL) return 1; return 0; } +#pragma weak free_config void free_config(struct daemon_conf *config) { free((void*)config->log_file); } diff -r -U5 audit-2.8.5-orig/auparse/interpret.c audit-2.8.5/auparse/interpret.c --- audit-2.8.5-orig/auparse/interpret.c 2019-03-01 20:19:13.000000000 +0000 +++ audit-2.8.5/auparse/interpret.c 2021-01-13 11:39:42.107217224 +0000 @@ -545,10 +545,11 @@ else snprintf(buf, size, "unknown(%d)", uid); return buf; } +#pragma weak aulookup_destroy_uid_list void aulookup_destroy_uid_list(void) { if (uid_cache_created == 0) return; @@ -2810,10 +2811,11 @@ /* * This is the main entry point for the auparse library. Call chain is: * auparse_interpret_field -> nvlist_interp_cur_val -> interpret */ +#pragma weak interpret const char *interpret(const rnode *r, auparse_esc_t escape_mode) { const nvlist *nv = &r->nv; int type; idata id; diff -r -U5 audit-2.8.5-orig/auparse/nvlist.c audit-2.8.5/auparse/nvlist.c --- audit-2.8.5-orig/auparse/nvlist.c 2019-02-04 14:26:52.000000000 +0000 +++ audit-2.8.5/auparse/nvlist.c 2021-01-13 11:37:37.190222757 +0000 @@ -27,10 +27,11 @@ #include "nvlist.h" #include "interpret.h" #include "auparse-idata.h" +#pragma weak nvlist_create void nvlist_create(nvlist *l) { l->head = NULL; l->cur = NULL; l->cnt = 0; @@ -47,17 +48,19 @@ while (node->next) node = node->next; l->cur = node; } +#pragma weak nvlist_next nvnode *nvlist_next(nvlist *l) { if (l->cur) l->cur = l->cur->next; return l->cur; } +#pragma weak nvlist_append void nvlist_append(nvlist *l, nvnode *node) { nvnode* newnode = malloc(sizeof(nvnode)); newnode->name = node->name; @@ -141,10 +144,11 @@ if (l->cur->interp_val) return l->cur->interp_val; return interpret(r, escape_mode); } +#pragma weak nvlist_clear void nvlist_clear(nvlist* l) { nvnode* nextnode; register nvnode* current; diff -r -U5 audit-2.8.5-orig/auparse/strsplit.c audit-2.8.5/auparse/strsplit.c --- audit-2.8.5-orig/auparse/strsplit.c 2019-03-01 21:15:30.000000000 +0000 +++ audit-2.8.5/auparse/strsplit.c 2021-01-13 11:38:04.306221556 +0000 @@ -54,10 +54,11 @@ return NULL; return s; } } +#pragma weak audit_strsplit char *audit_strsplit(char *s) { static char *str = NULL; char *ptr; diff -r -U5 audit-2.8.5-orig/lib/strsplit.c audit-2.8.5/lib/strsplit.c --- audit-2.8.5-orig/lib/strsplit.c 2019-03-01 20:19:13.000000000 +0000 +++ audit-2.8.5/lib/strsplit.c 2021-01-13 11:38:29.444220443 +0000 @@ -23,10 +23,11 @@ #include #include "libaudit.h" #include "private.h" +#pragma weak audit_strsplit_r char *audit_strsplit_r(char *s, char **savedpp) { char *ptr; if (s)