diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h index a4980af8a..ce83536ea 100644 --- a/include/haproxy/bug.h +++ b/include/haproxy/bug.h @@ -201,6 +201,7 @@ enum tainted_flags { TAINTED_WARN = 0x00000010, /* a WARN_ON triggered */ TAINTED_BUG = 0x00000020, /* a BUG_ON triggered */ TAINTED_SHARED_LIBS = 0x00000040, /* a shared library was loaded */ + TAINTED_REDEFINITION = 0x00000080, /* symbol redefinition detected */ }; /* this is a bit field made of TAINTED_*, and is declared in haproxy.c */ diff --git a/src/tools.c b/src/tools.c index 5a3502750..c2ee7c953 100644 --- a/src/tools.c +++ b/src/tools.c @@ -5810,7 +5810,21 @@ int openssl_compare_current_name(const char *name) void *dlopen(const char *filename, int flags) { static void *(*_dlopen)(const char *filename, int flags); + struct { + const char *name; + void *curr, *next; + } check_syms[] = { + { .name = "malloc", }, + { .name = "free", }, + { .name = "SSL_library_init", }, + { .name = "X509_free", }, + /* insert only above, 0 must be the last one */ + { 0 }, + }; + const char *trace; + void *addr; void *ret; + int sym = 0; if (!_dlopen) { _dlopen = get_sym_next_addr("dlopen"); @@ -5820,6 +5834,16 @@ void *dlopen(const char *filename, int flags) } } + /* save a few pointers to critical symbols. We keep a copy of both the + * current and the next value, because we might already have replaced + * some of them (e.g. malloc/free with DEBUG_MEM_STATS), and we're only + * interested in verifying that a loaded library doesn't come with a + * completely different definition that would be incompatible. + */ + for (sym = 0; check_syms[sym].name; sym++) { + check_syms[sym].curr = get_sym_curr_addr(check_syms[sym].name); + check_syms[sym].next = get_sym_next_addr(check_syms[sym].name); + } /* now open the requested lib */ ret = _dlopen(filename, flags); @@ -5828,6 +5852,25 @@ void *dlopen(const char *filename, int flags) mark_tainted(TAINTED_SHARED_LIBS); + /* and check that critical symbols didn't change */ + for (sym = 0; check_syms[sym].name; sym++) { + if (!check_syms[sym].curr && !check_syms[sym].next) + continue; + + addr = dlsym(ret, check_syms[sym].name); + if (!addr || addr == check_syms[sym].curr || addr == check_syms[sym].next) + continue; + + /* OK it's clear that this symbol was redefined */ + mark_tainted(TAINTED_REDEFINITION); + + trace = hlua_show_current_location("\n "); + ha_warning("dlopen(): shared library '%s' brings a different definition of symbol '%s'. The process cannot be trusted anymore!%s%s\n", + filename, check_syms[sym].name, + trace ? " Suspected call location: \n " : "", + trace ? trace : ""); + } + return ret; } #endif