UnixODBC+FreeTDS broken on FR3 on RHEL7 #1277

Closed
bluikko opened this Issue Sep 28, 2015 · 30 comments

Comments

Projects
None yet
7 participants

bluikko commented Sep 28, 2015

radiusd -X gives error when trying to use rlm_sql_unixodbc:

rlm_sql_unixodbc: 01000 [unixODBC][Driver Manager]Can't open lib '/usr/lib64/libtdsodbc.so.0' : ??????: undefined symbol: get_vtable

This is NOT ODBC/TDS problem with libraries or so, since I can connect to the database with the "isql" tool just fine.

CentOS 7, tested with following UnixODBC and FreeTDS versions:

  • UnixODBC: 2.3.4 and
  • FreeTDS 0.95.19 and 0.91
    With RHEL7 standard FreeRADIUS 3.0.4

Many people have raised this issue on various mailing lists over the past few years and nobody seems to have an answer!

Owner

alandekok commented Sep 28, 2015

There's nothing in the server which uses the "get_vtable" API. So the problem is in the libraries.

My guess is that the libraries suddenly require an additional library to be linked to the application. Or, the libraries are broken.

A simple google search yields this page:

http://fossies.org/dox/unixODBC-2.3.4/shl__load_8c.html

Which says:

#define     get_vtable   shl_load_LTX_get_vtable

So it's a library problem. The libraries were built such that they didn't define get_vtable correctly.

Please file a bug with CentOS and/or RedHat. Ask them to supply libraries which aren't broken.

There is nothing we can do to FreeRADIUS which will fix this problem.

alandekok closed this Sep 28, 2015

bluikko commented Sep 28, 2015

Thank you!
I saw you discussed this repeatedly in the mailing list but did not see this information. I will try to find out more and it is interesting nobody else has reported this outside of the mailing list posts.

Same issue in Ubuntu 14.04 with Freeradius 3.1.0

rlm_sql (sql): Opening additional connection (0), 1 of 32 pending slots used
rlm_sql_unixodbc: 01000 [unixODBC][Driver Manager]Can't open lib '/usr/lib/odbc/libtdsodbc.so' : ?F?!??: undefined symbol: get_vtable

bluikko commented Oct 3, 2015

Can you please give more information - what version of UnixODBC? Seems you use FreeTDS with it, what version? Also how did you install UnixODBC/FreeTDS, compile from source or install from a repository?

UnixODBC 2.2.14p2-5ubuntu5 and FreeTDS 0.91-5 installed from a repository . With this version of UnixODBC and FreeTDS in the same machine works without issue FreeRadius 2.1.12 with rlm_sql_unixodbc

Owner

arr2036 commented Oct 8, 2015

Check the linkages on 2.1.12 and 3.0.x, see how they differ?

bluikko commented Oct 8, 2015

That (gustavoheredia) does sound like a problem in FreeRADIUS or problem in build of FreeRADIUS...

edit: removed broken link

arr2036 reopened this Oct 9, 2015

bluiko i can`t see the link that you mentioned (Page not found)

bluikko commented Oct 9, 2015

Thanks, fixed

Owner

arr2036 commented Oct 31, 2015

What was the conclusion with this?

Owner

arr2036 commented Nov 27, 2015

Apparently nothing, i'll close the issue then...

arr2036 closed this Nov 27, 2015

bluikko commented Nov 27, 2015

No conclusion, your closing of the bug seems to be the only reply from FR side?

Owner

arr2036 commented Nov 27, 2015

arr2036 commented on Oct 7
Check the linkages on 2.1.12 and 3.0.x, see how they differ?
arr2036 commented 26 days ago
What was the conclusion with this?
Owner

arr2036 commented Nov 27, 2015

Did we receive any linkage information? no. If you're not willing to help diagnose this issue, i'm not going to keep it hanging around in the bug tracker.

bluikko commented Nov 27, 2015

I can do troubleshooting but I am not a developer. If there are some specific commands I can run to help, please list them. Otherwise I understand closing the bug if nobody would work on it anyways.

Owner

arr2036 commented Nov 27, 2015

Run ldd <path to rlm_unix_odbc.so> on the two systems, and compare/post the output.

arr2036 reopened this Nov 27, 2015

bluikko commented Nov 27, 2015

Not working:

$ cat /etc/centos-release
CentOS Linux release 7.1.1503 (Core)
$ rpm -qa |fgrep -i radius
freeradius-unixODBC-3.0.4-6.el7.x86_64
freeradius-3.0.4-6.el7.x86_64
$ rpm -qa |fgrep -i odbc
unixODBC-2.3.1-10.el7.x86_64
freeradius-unixODBC-3.0.4-6.el7.x86_64
$ rpm -qa |fgrep -i tds
freetds-0.91-12.git0a42888.el7.x86_64
$ ldd /usr/lib64/freeradius/rlm_sql_unixodbc.so
linux-vdso.so.1 => (0x00007ffe75f59000)
libodbc.so.2 => /usr/lib64/libodbc.so.2 (0x00007f9dbb41b000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007f9dbb05a000)
libltdl.so.7 => /usr/lib64/libltdl.so.7 (0x00007f9dbae4f000)
libdl.so.2 => /usr/lib64/libdl.so.2 (0x00007f9dbac4b000)
libpthread.so.0 => /usr/lib64/libpthread.so.0 (0x00007f9dbaa2f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9dbb888000)

Working:

$ cat /etc/centos-release
CentOS release 6.7 (Final)
$ rpm -qa |fgrep -i radius
freeradius-2.2.6-6.el6_7.x86_64
freeradius-utils-2.2.6-6.el6_7.x86_64
freeradius-unixODBC-2.2.6-6.el6_7.x86_64
$ rpm -qa |fgrep -i odbc
unixODBC-2.2.14-14.el6.x86_64
freeradius-unixODBC-2.2.6-6.el6_7.x86_64
$ rpm -qa |fgrep -i tds
freetds-0.91-2.el6.x86_64
$ ldd /usr/lib64/freeradius/rlm_sql_unixodbc-2.2.6.so
linux-vdso.so.1 => (0x00007ffe42ff6000)
libodbc.so.2 => /usr/lib64/libodbc.so.2 (0x00007f82e8034000)
libc.so.6 => /lib64/libc.so.6 (0x00007f82e7ca0000)
libltdl.so.7 => /usr/lib64/libltdl.so.7 (0x00007f82e7a96000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f82e7879000)
/lib64/ld-linux-x86-64.so.2 (0x0000003170800000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f82e7675000)

bluikko commented Nov 27, 2015

Seems to be the solution, so this bug can be closed.

alandekok closed this Nov 27, 2015

Collaborator

spbnick commented Nov 3, 2016

@alandekok, @arr2036, it appears there's more to this. We did a bit of research for our RHEL customers, and it appears the problem is that FreeRADIUS defines symbols lt_dlopenext, lt_dlsym, lt_dlclose, and lt_dlerror, which are also defined by libltdl, which is used by libodbc.

As a result, when rlm_sql_unixodbc loads libodbc, which in turn loads libltdl, it gets to use the FreeRADIUS version of those symbols, not the ones from libltdl. From this chaos ensues, including linker data corruption, as seen in those question marks in the output in the first message here.

My question is: does anything else use these, except the explicit uses in FreeRADIUS code, and can we perhaps rename these to avoid the clash? If yes, then I'll do the patch. If no, then what else uses this and what options do we have? Thank you.

Collaborator

spbnick commented Nov 3, 2016 edited

You can reproduce the problem with this command:

LD_PRELOAD=/usr/sbin/radiusd isql -v MSSQLTestServer

Provided you added this to /etc/odbcinst.ini:

[FreeTDS]
Description=v0.63 with protocol v8.0
Driver=/usr/lib64/libtdsodbc.so.0
UsageCount=1

And put this into /etc/odbc.ini:

[MSSQLTestServer]
Driver    = FreeTDS
Description = Sample database
Trace     = No
Server    = 127.0.0.1
Port      = 1433
Database  = Sample

Here is an excerpt from LD_DEBUG=all output:

  2324:     symbol=lt_dlsym;  lookup in file=isql [0]
  2324:     symbol=lt_dlsym;  lookup in file=/usr/sbin/radiusd [0]
  2324:     binding file /lib64/libltdl.so.7 [0] to /usr/sbin/radiusd [0]: normal symbol `lt_dlsym'

arr2036 reopened this Nov 3, 2016

Owner

arr2036 commented Nov 3, 2016

Ah, that's what's going on. I don't think they're used, just vestigial @alandekok?

Owner

alandekok commented Nov 3, 2016

They're used for the local dlopen wrappers. They could just as well be named fr_foo instead of lt_foo.

Collaborator

spbnick commented Nov 3, 2016

Alright, thanks Alan, Arran. I'll do a patch for v3.0.x renaming them to fr_* today or tomorrow, if you don't do it first.

@alandekok alandekok added a commit that referenced this issue Nov 3, 2016

@alandekok alandekok Rename lt_* to fr_*. Fixes #1277
Which fixes linker issues in libraries which link to libtool,
and then sometimes get the wrong function.

Changed via:

perl -p -i -e 's/lt_dlhandle/fr_dlhandle/g;s/lt_dlopenext/fr_dlopenext/g;s/lt_dlsym/fr_dlsym/g;s/lt_dlclose/fr_dlclose/g;s/lt_dlerror/fr_dlerror/g;' $(find . -name "*.[ch]" -print)
cb75828

alandekok closed this Nov 3, 2016

Collaborator

spbnick commented Nov 3, 2016

Thanks, Alan!

praiskup commented Nov 3, 2016

Thanks! Just a suggestion, it is always worth limiting the number of "exported symbols" as much as possible, so you avoid such linking issues in future. IOW, it is very rare case some symbol is going to be used (from binary), for example [1]. But again, thank you -> changing name-space should work for us.

[1] https://blog.flameeyes.eu/2008/02/why-would-an-executable-export-symbols/

Owner

arr2036 commented Nov 3, 2016

The symbols aren't exported in the radiusd bindary. They're exported in libfreeradius-server, which modules link to and is linked to by the radiusd binary.

praiskup commented Nov 3, 2016

That would mean the library is linked statically? But anyways:

$ readelf -s /usr/sbin/radiusd  | grep lt_dl
   611: 0000000000024550     5 FUNC    GLOBAL DEFAULT   13 lt_dlsym
   697: 0000000000024560    19 FUNC    GLOBAL DEFAULT   13 lt_dlclose
   753: 0000000000023da0   764 FUNC    GLOBAL DEFAULT   13 lt_dlopenext
   757: 0000000000024580     5 FUNC    GLOBAL DEFAULT   13 lt_dlerror

While

$ readelf -s /usr/lib64/freeradius/libfreeradius-server.so | grep lt_dl
[empty]
Owner

arr2036 commented Nov 3, 2016

It changed in v3.1.x/v4.0.x.

praiskup commented Nov 3, 2016 edited

Great, thanks for the info!

@lytboris lytboris pushed a commit to lytboris/freeradius-server that referenced this issue Nov 8, 2016

@alandekok alandekok + Boris Lytochkin Rename lt_* to fr_*. Fixes #1277
Which fixes linker issues in libraries which link to libtool,
and then sometimes get the wrong function.

Changed via:

perl -p -i -e 's/lt_dlhandle/fr_dlhandle/g;s/lt_dlopenext/fr_dlopenext/g;s/lt_dlsym/fr_dlsym/g;s/lt_dlclose/fr_dlclose/g;s/lt_dlerror/fr_dlerror/g;' $(find . -name "*.[ch]" -print)
40af09a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment