[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Library versions, SONAMEs,and symbol versions



On 2019-11-08 13:04 +0100, Steve Keller wrote:

> Could someone please explain how library version numbers, shared object
> names (SONAME), and symbol version are used in Debian?
>
> I have a problem with libcurl.so.4 and a binary linked against it.  In
> Debian stretch I have the package libcurl3 installed and can run a
> binary (I have no source code for it) linked against that libcurl.
>
> Although the package is libcurl3, it installs libcurl.so.4.4.0, with
> symlinks libcurl.so.4 and libcurl.so.3 pointing to it, and it has
> SONAME libcurl.so.4.

That is certainly rather unfortunate.  I think the reason is that in
curl 7.16 upstream changed the SONAME unnecessarily, and Debian decided
to provide both libcurl.so.4 and libcurl.so.3 in the same package.  See
the thread starting at [1].

> Many of the dynamic symbols are versioned as
> CURL_OPENSSL3 e.g.:
>
>   $nm -D --with-symbol-versions /usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0 | grep curl_easy_init
>   0000000000032430 T curl_easy_init@@CURL_OPENSSL_3
>
> and that's what my binary needs:
>
>   $ readelf -a my-binary | grep NEEDED.*curl
>    0x0000000000000001 (NEEDED)             Shared library: [libcurl.so.4]
>   $ nm -D --with-symbol-versions my-binary | grep curl_easy_init
>                  U curl_easy_init@CURL_OPENSSL_3
>
> In buster there is no libculr3 package but libcurl4, which installs
> libcurl.so.4.5.0 which also has SONAME libcurl.so.4 but the symbol
> versions have changed:
>
>   $ nm -D --with-symbol-versions libcurl.so.4.5.0 | grep curl_easy_init
>   000000000002f470 T curl_easy_init@@CURL_OPENSSL_4

Apparently the reason for this change was that the switch to openssl 1.1
caused an ABI break:

,----
| curl (7.60.0-2) unstable; urgency=medium
| 
|   [ Steve Langasek ]
|   * Rename libcurl3 to libcurl4, because libcurl exposes an SSL_CTX via
|     CURLOPT_SSL_CTX_FUNCTION, and this object changes incompatibly between
|     openssl 1.0 and openssl 1.1.
| 
|  -- Alessandro Ghedini <ghedo@debian.org>  Wed, 23 May 2018 20:25:39 +0100
`----


> That causes my-binary to fail because it doesn't find the needed
> symbol curl_easy_init@CURL_OPENSSL_3 in libcurl.so.4.
>
> So my questions are
>
> - Why do many libraries have version numbers that don't match their
>   SONAME?  I often find that confusing.

Not sure what you mean by "version number".  The library package's
_name_ should match the SONAME, which is usually the case, although
there are many exceptions[2].

> - Shouldn't a shared library's interface not change under any
>   circumstances unless it also changes its SONAME?  AFAIUI, that's the
>   whole idea behind SONAME: Interface and/or behavior changes always
>   cause the SONAME to be changed.

Ideally that would be the case, but it is not always possible.  For
instance, C++ libraries often experience ABI breaks when g++ defaults to
a new standard, and in this case it would not really be appropriate for
Debian to change the SONAME and deviate from upstream.  What is done in
such cases is to change the package name (as in the libcurl3 → libcurl4
case), which prevents programs from the distribution from crashing, but
does not help with locally installed software.

>   If new versions of symbols like curl_easy_init@CURL_OPENSSL_4 are
>   introduced, the old one must be kept for compatibility,
>   i.e. curl_easy_init@CURL_OPENSSL_3.
>
>   Otherwise, it's not even possible to install an old version of the
>   library to make my-binary run.  The problem is that the old library
>   would need to change the symlink libcurl.so.4 to point to the old
>   shared library file.  And again, I think this kills the main idea of
>   SONAMEs.
>
> - Given that some libraries don't do it that way, is there a way to
>   run a binary with ignoring the symbol versions?  I.e. I assuming that
>   the function curl_easy_init@CURL_OPENSSL_4 will work with my-binary,
>   can I run it using that new symbol instead of the old one, i.e. don't
>   care about the symbol version?

No, and actually it is one point of symbol versioning that this is not
possible.  What you can try is

- edit your program (might work, but is risky), e.g. with
  "sed -i /@CURL_OPENSSL_3/@CURL_OPENSSL_4/g my_program".

- the safe way would be to copy libcurl.so.4* to some directory not in
  the dynamic linker's search path and set LD_LIBRARY_PATH for your
  program.  This works as long it does not have the setuid or setgid bit
  set (ld.so ignores LD_LIBRARY_PATH for those due to security reasons).

Cheers,
       Sven


1. https://lists.debian.org/debian-release/2007/06/msg00106.html
2. https://lintian.debian.org/tags/package-name-doesnt-match-sonames.html


Reply to: