Bug 28877 - second call to dlopen fails to load a modified library binary
Summary: second call to dlopen fails to load a modified library binary
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: 2.28
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-02-09 21:27 UTC by Aral
Modified: 2022-02-09 21:27 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aral 2022-02-09 21:27:16 UTC
Scenario to reproduce requires:
- main application able to load/unload plugin.so on e.g. user keypress
- plugin.so with function
    void printVersion() { printf( "1\n" ); }

1) main is started & loads "plugin.so" 
2) main executes plugin's printPluginVersion -> "1"
3) main waits for user key press
4) plugin.so is modified to print "2" as version and recompiled
5) main is triggered to reload plugin (e.g. via keypress)
6) main unloads plugin.so via dlclose
7) main reloads plugin.so via dlopen
8) main executes plugin's printPluginVersion -> "1"(!!)

The new version of the plugin binary has not been loaded. An application restart will load the new version as expected in step 1 & 2

I believe the standard description for dlclose at
  https://pubs.opengroup.org/onlinepubs/007904975/functions/dlclose.html
is related, stating:

"Although a dlclose() operation is not required to remove structures from an address space, neither is an implementation prohibited from doing so."

It appears as though dlclose in the glibc does not remove the plugin from the address space and the subsequent dlopen just re-uses the already loaded plugin.

As it seems to be not prohibited by the standard, I would like to propose that dlopen *always* loads the requested library from the file system, and thereby the newest version.

Workaround that works as intended:
  string tempLink = randomFilenameOnSamePartition();
  link( file, tempLink.c_str() ); // create a hard link to file

  // attempt to open file via the hard link
  void *libraryHandle = dlopen( tempLink.c_str(), mode );

  unlink( tempLink.c_str() ); // delete the hard link right after use


If needed, I will be able to provide a proof of concept on the weekend. But it seems to be a 100% reproducible behavior and I could not find a different report on this. The closest related bug report seems to be
  https://sourceware.org/bugzilla/show_bug.cgi?id=16805