https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=246462
Bug ID: 246462 Summary: dlopen incorrect resolution of symbols [RTLD_DEEPBIND] Product: Base System Version: 12.1-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: bin Assignee: b...@freebsd.org Reporter: d8zne...@aon.at Introduction: This issue arose in the context of trying to upgrade a port (databases/postgresql-mysql_fdw) but is actually about the behavior of rtld/dlopen which seems to have changed (probably with the switch to clang/llvm). Scenario: - System running FreeBSD 12.1-RELEASE-p4 #4 r360692M - Ports at latest, mysql57-server and postgresql12-server installed - Trying to upgrade databases/postgresql-mysql_fdw from its current 2.5.1 to 2.5.3 Note: databases/postgresql-mysql_fdw is a foreign data wrapper which enables a Postgres server to access remote MySQL databases. Scenario (continued): - The upgrade is straightforward, just adapt the Makefile and distinfo, and it compiles and can be installed. - After installation, the local database is extended to be able to access the remote MySQL database using CREATE EXTENSION mysql_fdw; CREATE_SERVER ... CREATE USER MAPPING ... GRANT USAGE ON FOREIGN SERVER ... CREATE SCHEMA ... IMPORT FOREIGN SCHEMA ... - Then a foreign table is accessed using SELECT * FROM <foreign table>; Result: - When accessing the foreign table, the first access retrieves a correct result, and then the postgres process handling the postgres database client crashes with segmentation violation (signal 11), producing a core file. Scenario (continued): - Debugging the core file using lldb -c /tmp/postgres.core /usr/local/bin/postgres Result: (lldb) thread backtrace * thread #1, name = 'postgres', stop reason = signal SIGSEGV * frame #0: 0x00000000009002eb postgres`pfree + 11 frame #1: 0x00000000006a50de postgres`list_delete + 206 frame #2: 0x000000080b4f7d36 libmysqlclient.so`mysql_stmt_close + 102 Explanation: I believe what is happening here is that mysql_stmt_close calls list_delete, but this list_delete gets resolved to the version in the postgres binary instead of the function of the same name in libmysqlclient.so. This is because MySQL and Postgres are using the same names for different functions of their own, and in this case the wrong one is being called. A while ago, when the databases/postgresql-mysql_fdw port was last upgraded some years ago, this seemingly was not the case. Specifically, in the source code of this port one finds the following comment: /* * mysql_load_library function dynamically load the mysql's library * libmysqlclient.so. The only reason to load the library using dlopen * is that, mysql and postgres both have function with same name like * "list_delete", "list_delete" and "list_free" which cause compiler * error "duplicate function name" and erroneously linking with a function. * This port of the code is used to avoid the compiler error. * * #define list_delete mysql_list_delete * #include <mysql.h> * #undef list_delete * * But system crashed on function mysql_stmt_close function because * mysql_stmt_close internally calling "list_delete" function which * wrongly binds to postgres' "list_delete" function. * * The dlopen function provides a parameter "RTLD_DEEPBIND" which * solved the binding issue. * * RTLD_DEEPBIND: * Place the lookup scope of the symbols in this library ahead of the * global scope. This means that a self-contained library will use its * own symbols in preference to global symbols with the same name contained * in libraries that have already been loaded. */ bool mysql_load_library(void) { #if defined(__APPLE__) || defined(__FreeBSD__) /* * Mac OS/BSD does not support RTLD_DEEPBIND, but it still * works without the RTLD_DEEPBIND */ mysql_dll_handle = dlopen(_MYSQL_LIBNAME, RTLD_LAZY); #else mysql_dll_handle = dlopen(_MYSQL_LIBNAME, RTLD_LAZY | RTLD_DEEPBIND); #endif if(mysql_dll_handle == NULL) return false; Conclusion: It seems that the behavior of the runtime loader changed such that now the executable's symbols are searched before a library's symbols when resolving references arising from that library (in this case, libmysqlclient.so). It further seems that there are two possible resolutions: Either re-introduce the old behavior (which made it unnecessary to use RTLD_DEEPBIND in FreeBSD), or implement RTLD_DEEPBIND for FreeBSD. -- Martin -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ freebsd-bugs@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"