Skip site navigation (1)Skip section navigation (2)
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>