Re: [sr #111358] libtool link with -dlpreopen fails with error: cannot find the library '' or unhandled argument

Roland Hughes via Discussion list for the GNU libtool shared library maintenance tool <[email protected]> Thu, 2 Apr 2026 08:58:21 -0500
Newsgroups gmane.comp.gnu.libtool.general
Organization Logikal Solutions
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------CzwSodiNK9tsupzGOAG3OcRh
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

Thank you for your time Patrice.

How do I officially open a bug on this?  Use case is rather 
straightforward. If you want code already set up for it

https://github.com/RolandHughes/ls-cs

I'm working in a different branch so master will be fine for you. Just 
pull the code down then

sudo ./LsCs-Deb-build-dependencies.sh

just comment out the setting of RPATH in the xcb cmake files because 
that will be first to fail.

src/plugins/imageformats/svg/svg.cmake:14:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/imageformats"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:83:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:164:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:261:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/playlistformats/playlistformats.cmake:9:      INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/playlistformats"
src/plugins/platforms/xcb/glx/xcb_glx.cmake:17:      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/glx/xcb_glx.cmake:24:      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/glx/xcb_glx.cmake:38:          INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/xcbglintegrations"
src/plugins/platforms/xcb/glx/xcb_glx.cmake:49:          INSTALL_RPATH "$ORIGIN/../.."
src/plugins/platforms/xcb/xcb.cmake:11:     set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/xcb.cmake:18:     set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/xcb.cmake:32:          INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/platforms"
src/plugins/platforms/xcb/xcb.cmake:44:          INSTALL_RPATH "$ORIGIN/../.."
src/plugins/sqldrivers/mysql/mysql.cmake:22:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"
src/plugins/sqldrivers/odbc/odbc.cmake:21:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"
src/plugins/sqldrivers/psql/psql.cmake:22:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"

Then just

build-LsCs-local.sh

That will build the entire library creating the following directory tree.

roland@mxz2g4:~/cups-stuff/LsCs_local_release/lib
$ tree
.
└── LsCs
     ├── cmake
     │   ├── LsCsBinaryTargets.cmake
     │   ├── LsCsBinaryTargets-debug.cmake
     │   ├── LsCsConfig.cmake
     │   ├── LsCsConfigVersion.cmake
     │   ├── LsCsLibraryTargets.cmake
     │   ├── LsCsLibraryTargets-debug.cmake
     │   └── LsCsMacros.cmake
     ├── libLsCsCore.so -> libLsCsCore.so.0
     ├── libLsCsCore.so.0 -> libLsCsCore.so.0.3.2
     ├── libLsCsCore.so.0.3.2
     ├── libLsCsGui.so -> libLsCsGui.so.0
     ├── libLsCsGui.so.0 -> libLsCsGui.so.0.3.2
     ├── libLsCsGui.so.0.3.2
     ├── libLsCsMultimedia.so -> libLsCsMultimedia.so.0
     ├── libLsCsMultimedia.so.0 -> libLsCsMultimedia.so.0.3.2
     ├── libLsCsMultimedia.so.0.3.2
     ├── libLsCsNetwork.so -> libLsCsNetwork.so.0
     ├── libLsCsNetwork.so.0 -> libLsCsNetwork.so.0.3.2
     ├── libLsCsNetwork.so.0.3.2
     ├── libLsCsOpenGL.so -> libLsCsOpenGL.so.0
     ├── libLsCsOpenGL.so.0 -> libLsCsOpenGL.so.0.3.2
     ├── libLsCsOpenGL.so.0.3.2
     ├── libLsCsSql.so -> libLsCsSql.so.0
     ├── libLsCsSql.so.0 -> libLsCsSql.so.0.3.2
     ├── libLsCsSql.so.0.3.2
     ├── libLsCsSvg.so -> libLsCsSvg.so.0
     ├── libLsCsSvg.so.0 -> libLsCsSvg.so.0.3.2
     ├── libLsCsSvg.so.0.3.2
     ├── libLsCsXcbSupport.so -> libLsCsXcbSupport.so.0
     ├── libLsCsXcbSupport.so.0 -> libLsCsXcbSupport.so.0.3.2
     ├── libLsCsXcbSupport.so.0.3.2
     ├── libLsCsXmlPatterns.so -> libLsCsXmlPatterns.so.0
     ├── libLsCsXmlPatterns.so.0 -> libLsCsXmlPatterns.so.0.3.2
     ├── libLsCsXmlPatterns.so.0.3.2
     ├── libLsCsXml.so -> libLsCsXml.so.0
     ├── libLsCsXml.so.0 -> libLsCsXml.so.0.3.2
     ├── libLsCsXml.so.0.3.2
     └── plugins
         ├── imageformats
         │   └── LsCsImageFormatsSvg.so
         ├── mediaservices
         │   ├── LsCsMultimedia_gst_audiodecoder.so
         │   ├── LsCsMultimedia_gst_camerabin.so
         │   └── LsCsMultimedia_gst_mediaplayer.so
         ├── platforms
         │   └── LsCsGuiXcb.so
         ├── playlistformats
         │   └── LsCsMultimedia_m3u.so
         ├── sqldrivers
         │   ├── LsCsSqlMySql.so
         │   ├── LsCsSqlOdbc.so
         │   └── LsCsSqlPsql.so
         └── xcbglintegrations
             └── LsCsGuiXcb_Glx.so
10 directories, 47 files
roland@mxz2g4:~/cups-stuff/LsCs_local_release/lib
$


You will note that LsCsGuiXcb.so is in plugins/platforms under lib. It 
needs library files from the lib directory above it, but, when installed 
in a local tree, has no means of finding them without an insecure RPATH 
hack.

The local script automatically builds everything in debug.

cd to examples directory then

./build-examples.sh

choose option to build all if you wish. You only need gui-hello. 
console-hello doesn't use plugins so it works.

in src/core/plugin/qlibrary_unix.cpp around line 189 you will find a 
bunch of commented out code pulling library paths from the .conf file 
and inserting them into search path for lt_dlopen(). lines 256-267 are 
the lines where it once again uses dlopen() but has commented out the 
lt_dlopen() call.

USE_CASE:

lt_dlopen() should must use itself to open all library dependencies for 
any library/plugin it is used to load. It's the perfect tool for secure 
opens. A text .conf file is completely human/script auditable where as 
baked in RPATHs are not.

When a plugin that is further down the directory tree is loaded with 
lt_dlopen() if it needs library files from further up, this open fails, 
even if those library paths are in the search path for lt_dlopen(). This 
is because, per your source searches, the opening of dependencies is 
being handed off to dlopen() not recursively handled by lt_dlopen() itself.

DO NOT YET HAVE COMMENTED OUT CODE FOR THIS

I swear I tested this, but don't see the code still remaining.

dlopen() does not search the cache/index until it has found the full 
path to the library. Even if I pre-load

libLsCsCore.so.0.3.2

and all the other libraries the plugin needs dlopen() will fail without 
the RPATH hack because the cache/index doesn't store just the library 
name as above, but the full path. This is massive security hole because 
MyExe could preload wholesome and pure libLsCsCore from the 
trusted/vetted location and MyExe could call some other library method 
that loads libLsCsCore from /home/Fred/malware-tree/lib/

I don't know what would break in the field (probably only compromised 
programs) if the caching logic was changed.

COUNTER ARGUMENT

One could argue that allowing dynamic insertion like lt_dlopen() does is 
a bigger security hole. Well:

1) they would have to know a program is using it.

2) have to make their insertion before everything to loaded.

3) programs using lt_dlopen() can block malicious same-name libraries 
from getting loaded by having the main-line initialization code pre-load 
all valid libraries. Some combination of lt_dlopenadvise() with 
lt_dladvise_global() or, perhaps, lt_dlforeachfile() if one wishes to 
brute force.

Thank you again for looking into this matter.

When I get done with converting this library to XMake and getting CUPS 
3.x API support I was going to take another run at this dlopen() 
situation. Better if someone familiar with the code takes a run at it.

Please let me know if you need write access to the repo so you can 
create a GNU Testing branch that your team has access to. Yes, I know, 
most people want a 5 line test program, but . . . this is mostly 
watching scripts run.



On 4/2/2026 7:04 AM, Patrice Dumas wrote:
> Follow-up Comment #1, sr #111358 (group libtool):
>
> I had a look at the -dlpreopen use in the Debian code search, and this is used
> for in-source test executable linking and unless I missed something, I did not
> find any use with a library.  I do not know if it this information is useful
> but it could explain why this has not already been reported.
>
>
>      _______________________________________________________
>
> Reply to this item at:
>
>    <https://savannah.gnu.org/support/?111358>
>
> _______________________________________________
> Message sent via Savannah
> https://savannah.gnu.org/

-- 
Roland Hughes, President
Logikal Solutions
(630)-205-1593  (cell)
https://theminimumyouneedtoknow.com
https://infiniteexposure.net
https://johnsmith-book.com

--------------CzwSodiNK9tsupzGOAG3OcRh
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Thank you for your time Patrice.</p>
    <p>How do I officially open a bug on this?  Use case is rather
      straightforward. If you want code already set up for it</p>
    <p><a class="moz-txt-link-freetext" href="https://github.com/RolandHughes/ls-cs">https://github.com/RolandHughes/ls-cs</a></p>
    <p>I'm working in a different branch so master will be fine for you.
      Just pull the code down then</p>
    <pre>sudo ./LsCs-Deb-build-dependencies.sh</pre>
    <p>just comment out the setting of RPATH in the xcb cmake files
      because that will be first to fail.</p>
    <pre>src/plugins/imageformats/svg/svg.cmake:14:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/imageformats"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:83:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:164:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/mediaservices/gstreamer/gstreamer.cmake:261:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/mediaservices"
src/plugins/multimedia/playlistformats/playlistformats.cmake:9:      INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/playlistformats"
src/plugins/platforms/xcb/glx/xcb_glx.cmake:17:      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/glx/xcb_glx.cmake:24:      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/glx/xcb_glx.cmake:38:          INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/xcbglintegrations"
src/plugins/platforms/xcb/glx/xcb_glx.cmake:49:          INSTALL_RPATH "$ORIGIN/../.."
src/plugins/platforms/xcb/xcb.cmake:11:     set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/xcb.cmake:18:     set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
src/plugins/platforms/xcb/xcb.cmake:32:          INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/platforms"
src/plugins/platforms/xcb/xcb.cmake:44:          INSTALL_RPATH "$ORIGIN/../.."
src/plugins/sqldrivers/mysql/mysql.cmake:22:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"
src/plugins/sqldrivers/odbc/odbc.cmake:21:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"
src/plugins/sqldrivers/psql/psql.cmake:22:         INSTALL_RPATH "${LSCS_INST_PREFIX}/${LSCS_INST_LIB};${LSCS_INST_PREFIX}/${LSCS_INST_LIB}/plugins/sqldrivers"</pre>
    <p>Then just</p>
    <pre>build-LsCs-local.sh</pre>
    <p>That will build the entire library creating the following
      directory tree.</p>
    <pre>roland@mxz2g4:~/cups-stuff/LsCs_local_release/lib
$ tree
.
└── LsCs
    ├── cmake
    │   ├── LsCsBinaryTargets.cmake
    │   ├── LsCsBinaryTargets-debug.cmake
    │   ├── LsCsConfig.cmake
    │   ├── LsCsConfigVersion.cmake
    │   ├── LsCsLibraryTargets.cmake
    │   ├── LsCsLibraryTargets-debug.cmake
    │   └── LsCsMacros.cmake
    ├── libLsCsCore.so -&gt; libLsCsCore.so.0
    ├── libLsCsCore.so.0 -&gt; libLsCsCore.so.0.3.2
    ├── libLsCsCore.so.0.3.2
    ├── libLsCsGui.so -&gt; libLsCsGui.so.0
    ├── libLsCsGui.so.0 -&gt; libLsCsGui.so.0.3.2
    ├── libLsCsGui.so.0.3.2
    ├── libLsCsMultimedia.so -&gt; libLsCsMultimedia.so.0
    ├── libLsCsMultimedia.so.0 -&gt; libLsCsMultimedia.so.0.3.2
    ├── libLsCsMultimedia.so.0.3.2
    ├── libLsCsNetwork.so -&gt; libLsCsNetwork.so.0
    ├── libLsCsNetwork.so.0 -&gt; libLsCsNetwork.so.0.3.2
    ├── libLsCsNetwork.so.0.3.2
    ├── libLsCsOpenGL.so -&gt; libLsCsOpenGL.so.0
    ├── libLsCsOpenGL.so.0 -&gt; libLsCsOpenGL.so.0.3.2
    ├── libLsCsOpenGL.so.0.3.2
    ├── libLsCsSql.so -&gt; libLsCsSql.so.0
    ├── libLsCsSql.so.0 -&gt; libLsCsSql.so.0.3.2
    ├── libLsCsSql.so.0.3.2
    ├── libLsCsSvg.so -&gt; libLsCsSvg.so.0
    ├── libLsCsSvg.so.0 -&gt; libLsCsSvg.so.0.3.2
    ├── libLsCsSvg.so.0.3.2
    ├── libLsCsXcbSupport.so -&gt; libLsCsXcbSupport.so.0
    ├── libLsCsXcbSupport.so.0 -&gt; libLsCsXcbSupport.so.0.3.2
    ├── libLsCsXcbSupport.so.0.3.2
    ├── libLsCsXmlPatterns.so -&gt; libLsCsXmlPatterns.so.0
    ├── libLsCsXmlPatterns.so.0 -&gt; libLsCsXmlPatterns.so.0.3.2
    ├── libLsCsXmlPatterns.so.0.3.2
    ├── libLsCsXml.so -&gt; libLsCsXml.so.0
    ├── libLsCsXml.so.0 -&gt; libLsCsXml.so.0.3.2
    ├── libLsCsXml.so.0.3.2
    └── plugins
        ├── imageformats
        │   └── LsCsImageFormatsSvg.so
        ├── mediaservices
        │   ├── LsCsMultimedia_gst_audiodecoder.so
        │   ├── LsCsMultimedia_gst_camerabin.so
        │   └── LsCsMultimedia_gst_mediaplayer.so
        ├── platforms
        │   └── LsCsGuiXcb.so
        ├── playlistformats
        │   └── LsCsMultimedia_m3u.so
        ├── sqldrivers
        │   ├── LsCsSqlMySql.so
        │   ├── LsCsSqlOdbc.so
        │   └── LsCsSqlPsql.so
        └── xcbglintegrations
            └── LsCsGuiXcb_Glx.so
10 directories, 47 files
roland@mxz2g4:~/cups-stuff/LsCs_local_release/lib
$ </pre>
    <p><br>
      You will note that LsCsGuiXcb.so is in plugins/platforms under
      lib. It needs library files from the lib directory above it, but,
      when installed in a local tree, has no means of finding them
      without an insecure RPATH hack.</p>
    <p>The local script automatically builds everything in debug.</p>
    <p>cd to examples directory then</p>
    <pre>./build-examples.sh</pre>
    <p>choose option to build all if you wish. You only need gui-hello.
      console-hello doesn't use plugins so it works.</p>
    <p>in src/core/plugin/qlibrary_unix.cpp around line 189 you will
      find a bunch of commented out code pulling library paths from the
      .conf file and inserting them into search path for lt_dlopen().
      lines 256-267 are the lines where it once again uses dlopen() but
      has commented out the lt_dlopen() call.</p>
    <p>USE_CASE:</p>
    <p>lt_dlopen() should must use itself to open all library
      dependencies for any library/plugin it is used to load. It's the
      perfect tool for secure opens. A text .conf file is completely
      human/script auditable where as baked in RPATHs are not.</p>
    <p>When a plugin that is further down the directory tree is loaded
      with lt_dlopen() if it needs library files from further up, this
      open fails, even if those library paths are in the search path for
      lt_dlopen(). This is because, per your source searches, the
      opening of dependencies is being handed off to dlopen() not
      recursively handled by lt_dlopen() itself.</p>
    <p>DO NOT YET HAVE COMMENTED OUT CODE FOR THIS</p>
    <p>I swear I tested this, but don't see the code still remaining.</p>
    <p>dlopen() does not search the cache/index until it has found the
      full path to the library. Even if I pre-load </p>
    <pre>libLsCsCore.so.0.3.2</pre>
    <p>and all the other libraries the plugin needs dlopen() will fail
      without the RPATH hack because the cache/index doesn't store just
      the library name as above, but the full path. This is massive
      security hole because MyExe could preload wholesome and pure
      libLsCsCore from the trusted/vetted location and MyExe could call
      some other library method that loads libLsCsCore from
      /home/Fred/malware-tree/lib/</p>
    <p>I don't know what would break in the field (probably only
      compromised programs) if the caching logic was changed.</p>
    <p>COUNTER ARGUMENT</p>
    <p>One could argue that allowing dynamic insertion like lt_dlopen()
      does is a bigger security hole. Well:</p>
    <p>1) they would have to know a program is using it.</p>
    <p>2) have to make their insertion before everything to loaded.</p>
    <p>3) programs using lt_dlopen() can block malicious same-name
      libraries from getting loaded by having the main-line
      initialization code pre-load all valid libraries. Some combination
      of lt_dlopenadvise() with lt_dladvise_global() or, perhaps,
      lt_dlforeachfile() if one wishes to brute force.</p>
    <p>Thank you again for looking into this matter.</p>
    <p>When I get done with converting this library to XMake and getting
      CUPS 3.x API support I was going to take another run at this
      dlopen() situation. Better if someone familiar with the code takes
      a run at it.</p>
    <p>Please let me know if you need write access to the repo so you
      can create a GNU Testing branch that your team has access to. Yes,
      I know, most people want a 5 line test program, but . . . this is
      mostly watching scripts run.</p>
    <p><br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 4/2/2026 7:04 AM, Patrice Dumas
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:[email protected]">
      <pre wrap="" class="moz-quote-pre">Follow-up Comment #1, sr #111358 (group libtool):

I had a look at the -dlpreopen use in the Debian code search, and this is used
for in-source test executable linking and unless I missed something, I did not
find any use with a library.  I do not know if it this information is useful
but it could explain why this has not already been reported.


    _______________________________________________________

Reply to this item at:

  <a class="moz-txt-link-rfc2396E" href="https://savannah.gnu.org/support/?111358">&lt;https://savannah.gnu.org/support/?111358&gt;</a>

_______________________________________________
Message sent via Savannah
<a class="moz-txt-link-freetext" href="https://savannah.gnu.org/">https://savannah.gnu.org/</a>
</pre>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Roland Hughes, President
Logikal Solutions
(630)-205-1593  (cell)
<a class="moz-txt-link-freetext" href="https://theminimumyouneedtoknow.com">https://theminimumyouneedtoknow.com</a>
<a class="moz-txt-link-freetext" href="https://infiniteexposure.net">https://infiniteexposure.net</a>
<a class="moz-txt-link-freetext" href="https://johnsmith-book.com">https://johnsmith-book.com</a></pre>
  </body>
</html>

--------------CzwSodiNK9tsupzGOAG3OcRh--