8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:43:02 +01:00

Adjust logic of POSIX DlfcnModule::findSymbol to avoid problems when same library is loaded through different file names (symbolic links / directly).

This commit is contained in:
Adriano dos Santos Fernandes 2022-04-21 15:18:17 -03:00
parent b7e0d36b07
commit 94299500fe
2 changed files with 65 additions and 45 deletions

View File

@ -73,7 +73,7 @@ public:
const Firebird::PathName fileName; const Firebird::PathName fileName;
#ifdef LINUX #ifdef LINUX
virtual bool getRealPath(Firebird::PathName& realPath) = 0; virtual bool getRealPath(Firebird::PathName& path) = 0;
#endif #endif
protected: protected:

View File

@ -46,18 +46,16 @@
class DlfcnModule : public ModuleLoader::Module class DlfcnModule : public ModuleLoader::Module
{ {
public: public:
DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m) DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m);
: ModuleLoader::Module(pool, aFileName),
module(m)
{}
~DlfcnModule(); ~DlfcnModule();
void* findSymbol(ISC_STATUS*, const Firebird::string&);
bool getRealPath(Firebird::PathName& realPath); void* findSymbol(ISC_STATUS*, const Firebird::string&) override;
bool getRealPath(Firebird::PathName& path) override;
private: private:
void* module; void* module;
Firebird::PathName realPath;
}; };
static void makeErrorStatus(ISC_STATUS* status, const char* text) static void makeErrorStatus(ISC_STATUS* status, const char* text)
@ -154,6 +152,47 @@ ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebir
return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), linkPath, module); return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), linkPath, module);
} }
DlfcnModule::DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m)
: ModuleLoader::Module(pool, aFileName),
module(m),
realPath(pool)
{
#ifdef HAVE_DLINFO
char b[PATH_MAX];
#ifdef HAVE_RTLD_DI_ORIGIN
if (dlinfo(module, RTLD_DI_ORIGIN, b) == 0)
{
realPath = b;
realPath += '/';
realPath += fileName;
if (realpath(realPath.c_str(), b))
{
realPath = b;
return;
}
}
#endif
#ifdef HAVE_RTLD_DI_LINKMAP
struct link_map* lm;
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
{
if (realpath(lm->l_name, b))
{
realPath = b;
return;
}
}
#endif
#endif
// Error getting real path.
realPath.clear();
}
DlfcnModule::~DlfcnModule() DlfcnModule::~DlfcnModule()
{ {
if (module) if (module)
@ -165,7 +204,7 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
void* result = dlsym(module, symName.c_str()); void* result = dlsym(module, symName.c_str());
if (!result) if (!result)
{ {
Firebird::string newSym ='_' + symName; Firebird::string newSym = '_' + symName;
result = dlsym(module, newSym.c_str()); result = dlsym(module, newSym.c_str());
} }
@ -183,20 +222,28 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
return NULL; return NULL;
} }
const auto& libraryPath = realPath.isEmpty() ? fileName : realPath;
char symbolPathBuffer[PATH_MAX];
const char* symbolPath = symbolPathBuffer;
if (!realpath(info.dli_fname, symbolPathBuffer))
symbolPath = info.dli_fname;
const char* errText = "Actual module name does not match requested"; const char* errText = "Actual module name does not match requested";
if (PathUtils::isRelative(fileName) || PathUtils::isRelative(info.dli_fname)) if (PathUtils::isRelative(libraryPath) || PathUtils::isRelative(symbolPath))
{ {
// check only name (not path) of the library // check only name (not path) of the library
Firebird::PathName dummyDir, nm1, nm2; Firebird::PathName dummyDir, nm1, nm2;
PathUtils::splitLastComponent(dummyDir, nm1, fileName); PathUtils::splitLastComponent(dummyDir, nm1, libraryPath);
PathUtils::splitLastComponent(dummyDir, nm2, info.dli_fname); PathUtils::splitLastComponent(dummyDir, nm2, symbolPath);
if (nm1 != nm2) if (nm1 != nm2)
{ {
makeErrorStatus(status, errText); makeErrorStatus(status, errText);
return NULL; return NULL;
} }
} }
else if (fileName != info.dli_fname) else if (libraryPath != symbolPath)
{ {
makeErrorStatus(status, errText); makeErrorStatus(status, errText);
return NULL; return NULL;
@ -206,38 +253,11 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
return result; return result;
} }
bool DlfcnModule::getRealPath(Firebird::PathName& realPath) bool DlfcnModule::getRealPath(Firebird::PathName& path)
{ {
#ifdef HAVE_DLINFO if (realPath.isEmpty())
char b[PATH_MAX]; return false;
#ifdef HAVE_RTLD_DI_ORIGIN path = realPath;
if (dlinfo(module, RTLD_DI_ORIGIN, b) == 0) return true;
{
realPath = b;
realPath += '/';
realPath += fileName;
if (realpath(realPath.c_str(), b))
{
realPath = b;
return true;
}
}
#endif
#ifdef HAVE_RTLD_DI_LINKMAP
struct link_map* lm;
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
{
if (realpath(lm->l_name, b))
{
realPath = b;
return true;
}
}
#endif
#endif
return false;
} }