Skip to content

Commit 4d664d5

Browse files
authored
MONGOCRYPT-738 Improve error on failure to load crypt_shared (#981)
* refer to `crypt_shared`, not `CSFLE` in logs and error messages * set error status on failure to load symbols Fixes the error message: `Load error: [(null)]` to `Load error: [...]` * check for `mongocrypt_version` symbol. Return a more informative error if path to libmongocrypt was accidentally specified.
1 parent edc8bf9 commit 4d664d5

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ target_compile_definitions (test-mongocrypt PRIVATE
533533
"TEST_MONGOCRYPT_OUTPUT_PATH=\"$<TARGET_FILE:test-mongocrypt>\""
534534
# Tell test-mongocrypt whether we have a real csfle library for testing
535535
TEST_MONGOCRYPT_HAVE_REAL_CRYPT_SHARED_LIB=$<BOOL:${MONGOCRYPT_TESTING_CRYPT_SHARED_FILE}>
536+
# Tell test-mongocrypt the path of the libmongocrypt shared library for testing.
537+
"TEST_MONGOCRYPT_MONGOCRYPT_SHARED_PATH=\"$<TARGET_FILE:mongocrypt>\""
536538
)
537539

538540
add_test (

src/mongocrypt.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,10 @@ static _loaded_csfle _try_load_csfle(const char *filepath, mongocrypt_status_t *
397397
// Error opening candidate
398398
_mongocrypt_log(log,
399399
MONGOCRYPT_LOG_LEVEL_WARNING,
400-
"Error while opening candidate for CSFLE dynamic library [%s]: %s",
400+
"Error while opening candidate for crypt_shared dynamic library [%s]: %s",
401401
filepath,
402402
lib.error_string.raw.data);
403-
CLIENT_ERR("Error while opening candidate for CSFLE dynamic library [%s]: %s",
403+
CLIENT_ERR("Error while opening candidate for crypt_shared dynamic library [%s]: %s",
404404
filepath,
405405
lib.error_string.raw.data);
406406
// Free resources, which will include the error string
@@ -410,7 +410,7 @@ static _loaded_csfle _try_load_csfle(const char *filepath, mongocrypt_status_t *
410410
}
411411

412412
// Successfully opened DLL
413-
_mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_TRACE, "Loading CSFLE dynamic library [%s]", filepath);
413+
_mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_TRACE, "Loading crypt_shared dynamic library [%s]", filepath);
414414

415415
// Construct the library vtable
416416
_mongo_crypt_v1_vtable vtable = {.okay = true};
@@ -425,7 +425,7 @@ static _loaded_csfle _try_load_csfle(const char *filepath, mongocrypt_status_t *
425425
/* The requested symbol is not present */ \
426426
_mongocrypt_log(log, \
427427
MONGOCRYPT_LOG_LEVEL_ERROR, \
428-
"Missing required symbol '%s' from CSFLE dynamic library [%s]", \
428+
"Missing required symbol '%s' from crypt_shared dynamic library [%s]", \
429429
symname, \
430430
filepath); \
431431
/* Mark the vtable as broken, but keep trying to load more symbols to \
@@ -437,17 +437,27 @@ static _loaded_csfle _try_load_csfle(const char *filepath, mongocrypt_status_t *
437437
#undef X_FUNC
438438

439439
if (!vtable.okay) {
440+
// A common mistake is to pass the path to libmongocrypt instead of than crypt_shared.
441+
// Check if the library has a libmongocrypt symbol.
442+
if (mcr_dll_sym(lib, "mongocrypt_version")) {
443+
CLIENT_ERR("Tried to load crypt_shared dynamic library at path [%s] but detected libmongocrypt", filepath);
444+
mcr_dll_close(lib);
445+
return (_loaded_csfle){.okay = false};
446+
}
440447
mcr_dll_close(lib);
441448
_mongocrypt_log(log,
442449
MONGOCRYPT_LOG_LEVEL_ERROR,
443-
"One or more required symbols are missing from CSFLE dynamic library "
450+
"One or more required symbols are missing from crypt_shared dynamic library "
444451
"[%s], so this dynamic library will not be used.",
445452
filepath);
453+
CLIENT_ERR("One or more required symbols are missing from crypt_shared dynamic library "
454+
"[%s], so this dynamic library will not be used.",
455+
filepath);
446456
return (_loaded_csfle){.okay = false};
447457
}
448458

449459
// Success!
450-
_mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_INFO, "Opened CSFLE dynamic library [%s]", filepath);
460+
_mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_INFO, "Opened crypt_shared dynamic library [%s]", filepath);
451461
return (_loaded_csfle){.okay = true, .lib = lib, .vtable = vtable};
452462
}
453463

@@ -481,7 +491,7 @@ static bool _try_replace_dollar_origin(mstr *filepath, _mongocrypt_log_t *log) {
481491
_mongocrypt_log(log,
482492
MONGOCRYPT_LOG_LEVEL_WARNING,
483493
"Error while loading the executable module path for "
484-
"substitution of $ORIGIN in CSFLE search path [%s]: %s",
494+
"substitution of $ORIGIN in crypt_shared search path [%s]: %s",
485495
filepath->raw.data,
486496
error.raw.data);
487497
mstr_free(error);
@@ -597,7 +607,7 @@ static bool _validate_csfle_singleton(mongocrypt_t *crypt, _loaded_csfle found)
597607
bool okay = true;
598608
if (!found.okay) {
599609
// There is one loaded, but we failed to find that same library. Error:
600-
CLIENT_ERR("An existing CSFLE library is loaded by the application at "
610+
CLIENT_ERR("An existing crypt_shared library is loaded by the application at "
601611
"[%s], but the current call to mongocrypt_init() failed to "
602612
"find that same library.",
603613
existing_path.data);
@@ -611,9 +621,9 @@ static bool _validate_csfle_singleton(mongocrypt_t *crypt, _loaded_csfle found)
611621
if (!mstr_eq(found_path.path.view, existing_path)) {
612622
// Our find-result should only ever find the existing same library.
613623
// Error:
614-
CLIENT_ERR("An existing CSFLE library is loaded by the application at [%s], "
624+
CLIENT_ERR("An existing crypt_shared library is loaded by the application at [%s], "
615625
"but the current call to mongocrypt_init() attempted to load a "
616-
"second CSFLE library from [%s]. This is not allowed.",
626+
"second crypt_shared library from [%s]. This is not allowed.",
617627
existing_path.data,
618628
found_path.path.raw.data);
619629
okay = false;

test/test-mongocrypt-csfle-lib.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static void _test_csfle_load_twice_fail(_mongocrypt_tester_t *tester) {
9696
mongocrypt_t *const crypt2 = get_test_mongocrypt(tester);
9797
mongocrypt_setopt_set_crypt_shared_lib_path_override(crypt2, "$ORIGIN/stubbed-crypt_shared-2.dll");
9898
// Loading a second different library is an error:
99-
ASSERT_FAILS(_mongocrypt_init_for_test(crypt2), crypt2, "attempted to load a second CSFLE library");
99+
ASSERT_FAILS(_mongocrypt_init_for_test(crypt2), crypt2, "attempted to load a second crypt_shared library");
100100

101101
mstr_view version = mstrv_view_cstr(mongocrypt_crypt_shared_lib_version_string(crypt1, NULL));
102102
if (TEST_MONGOCRYPT_HAVE_REAL_CRYPT_SHARED_LIB) {
@@ -190,6 +190,15 @@ static void _test_lookup_version_check(_mongocrypt_tester_t *tester) {
190190
mongocrypt_destroy(crypt);
191191
}
192192

193+
static void _test_loading_libmongocrypt_fails(_mongocrypt_tester_t *tester) {
194+
mongocrypt_t *const crypt = get_test_mongocrypt(tester);
195+
const char *path_to_libmongocrypt = TEST_MONGOCRYPT_MONGOCRYPT_SHARED_PATH;
196+
mongocrypt_setopt_set_crypt_shared_lib_path_override(crypt, path_to_libmongocrypt);
197+
bool ok = mongocrypt_init(crypt);
198+
ASSERT_FAILS(ok, crypt, "detected libmongocrypt");
199+
mongocrypt_destroy(crypt);
200+
}
201+
193202
void _mongocrypt_tester_install_csfle_lib(_mongocrypt_tester_t *tester) {
194203
INSTALL_TEST(_test_csfle_no_paths);
195204
INSTALL_TEST(_test_csfle_not_found);
@@ -202,4 +211,5 @@ void _mongocrypt_tester_install_csfle_lib(_mongocrypt_tester_t *tester) {
202211
INSTALL_TEST(_test_csfle_not_loaded_with_bypassqueryanalysis);
203212
INSTALL_TEST(_test_override_error_includes_reason);
204213
INSTALL_TEST(_test_lookup_version_check);
214+
INSTALL_TEST(_test_loading_libmongocrypt_fails);
205215
}

0 commit comments

Comments
 (0)