Date: Thu, 14 May 2020 08:14:57 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 246462] dlopen incorrect resolution of symbols [RTLD_DEEPBIND] Message-ID: <bug-246462-227@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D246462 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: bugs@FreeBSD.org Reporter: d8zNeCFG@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 enable= s 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 t= he 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 =3D 'postgres', stop reason =3D 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 postg= res 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 =3D dlopen(_MYSQL_LIBNAME, RTLD_LAZY); #else mysql_dll_handle =3D dlopen(_MYSQL_LIBNAME, RTLD_LAZY | RTLD_DEEPBI= ND); #endif if(mysql_dll_handle =3D=3D NULL) return false; Conclusion: It seems that the behavior of the runtime loader changed such t= hat 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 resolution= s: Either re-introduce the old behavior (which made it unnecessary to use RTLD_DEEPBIND in FreeBSD), or implement RTLD_DEEPBIND for FreeBSD. -- Martin --=20 You are receiving this mail because: You are the assignee for the bug.=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-246462-227>