[MONGOCRYPT-421] CSFLE shared library from previous mongocrypt_t is unexpectedly reused Created: 19/Apr/22  Updated: 08/Jul/22  Resolved: 06/Jun/22

Status: Closed
Project: Libmongocrypt
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Anna Henningsen Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
is depended on by NODE-4089 Enable CSFLE shared library AutoEncry... Closed
Binding Changes: Not Needed

 Description   

https://mongodb.slack.com/archives/C02TYVCDYHZ/p1650373327707989

There’s something weird going on with the global csfle library state management. In a situation in which there is no global system csfle library, if a mongocrypt_t is initialized with csfleSearchPaths: ['$SYSTEM'], the library is being used even if there is no global shared library but if another mongocrypt_t was previously initialized with csflePath set to a shared library path

i.e.

> new MongoCrypt({ csfleSearchPaths: ['$SYSTEM'] }).csfleVersionInfo
null
> new MongoCrypt({ }).csfleVersionInfo
null
> new MongoCrypt({ csflePath: '/.../mongo_csfle_v1.so', csfleSearchPaths: ['$SYSTEM'] }).csfleVersionInfo
{ version: 105553653141504n, versionStr: 'stubbed-mongo_csfle' }
> new MongoCrypt({ csfleSearchPaths: ['$SYSTEM'] }).csfleVersionInfo
{ version: 105553653141504n, versionStr: 'stubbed-mongo_csfle' }
> new MongoCrypt({ }).csfleVersionInfo
null
even though the 4th call and the 1st one specify the same options



 Comments   
Comment by Durran Jordan [ 08/Jul/22 ]

Just adding as a note here that we ran into this in the Node driver when we wanted to do testing in the same suite with both the shared library and libmongocryptd. Our workaround is to run the suite in different processes for each, but we still run into this when testing behaviour of the shared library for valid/invalid scenarios - once the shared library is loaded once and we try to load with different parameters the original shared library is still loaded.

Comment by Anna Henningsen [ 04/May/22 ]

Yeah, that’s absolutely possible, I didn’t try Windows for this.

Comment by Colby Pike [ 04/May/22 ]

That's definitely not what I expected. I will investigate. (I believe Window's LoadLibrary still does this, though, since it cares about filenames instead of SONAMEs.)

Comment by Anna Henningsen [ 26/Apr/22 ]

colby.pike@mongodb.com You mean like this?

$ cat test.c
#include <dlfcn.h>
#include <stdio.h>
 
void dummy_so_shared_object_is_not_empty() {}
 
#ifdef MAIN
int main() {
  void* handle_1 = dlopen("/tmp/test.so", RTLD_LOCAL | RTLD_LAZY);
  fprintf(stderr, "handle_1 = %p (%s)\n", handle_1, dlerror());
 
  void* handle_2 = dlopen("test.so", RTLD_LOCAL | RTLD_LAZY);
  fprintf(stderr, "handle_2 = %p (%s)\n", handle_2, dlerror());
}
#endif
$ gcc -fPIC -shared -o test.so test.c && gcc -DMAIN -o test test.c -ldl && ./test
handle_1 = 0x55d362d722c0 ((null))
handle_2 = (nil) (test.so: cannot open shared object file: No such file or directory)

Comment by Colby Pike [ 25/Apr/22 ]

IIRC, LoadLibrary() on Windows has the same "helpful" behavior based on the filename of the library, so it will at least be consistently foolish.

Comment by Colby Pike [ 25/Apr/22 ]

I had a suspicion that I ran into this but was unsure if it was really what I was seeing.

I believe this is just the way dlopen() works when you provide only a filename. Because you have previously loaded a DSO with a filename (SONAME?) Foo, even if using a qualified path, subsequent attempts to "search" for a DSO using only the filename Foo will hit an in-process lookup table that matches the filename (SONAME?) of the prior loaded DSO and so the "system search" immediately resolves to the previously-loaded DSO.

Generated at Thu Feb 08 09:08:38 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.