Skip to content

Commit 40026ed

Browse files
committed
Fix read-only LMDB lookup DBI lifetime
The read-only fapolicyd-cli --check-path setup opened the active LMDB named database and then aborted the transaction. LMDB keeps DBI handles opened by mdb_dbi_open() private to the opening transaction until that transaction commits, so the aborted setup transaction could invalidate readonly_lookup_dbi and make later cursor opens fail. Commit the read-only setup transaction after opening the active DBI, and keep abort handling for setup failures. This preserves the private read-only environment while making the DBI usable by subsequent read-only lookup transactions. Add a trustdb_lmdb_test regression that publishes a temporary trust record, closes the writable test environment, starts the CLI read-only lookup state, and verifies the trusted path is found through a later transaction.
1 parent 6f9a1b9 commit 40026ed

2 files changed

Lines changed: 54 additions & 3 deletions

File tree

src/library/database.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5078,18 +5078,25 @@ int database_readonly_lookup_start(void)
50785078
if (rc)
50795079
goto out_abort;
50805080

5081+
/*
5082+
* LMDB DBI handles opened in a transaction stay private until that
5083+
* transaction commits. Aborting here would close readonly_lookup_dbi
5084+
* before check_trust_database_readonly() starts its lookup transaction.
5085+
*/
5086+
rc = mdb_txn_commit(txn);
5087+
if (rc)
5088+
goto error;
5089+
50815090
MDB_maxkeysize = mdb_env_get_maxkeysize(readonly_lookup_env);
50825091
lib_symlink = is_link("/lib");
50835092
lib64_symlink = is_link("/lib64");
50845093
bin_symlink = is_link("/bin");
50855094
sbin_symlink = is_link("/sbin");
50865095
readonly_lookup_open = 1;
5096+
return 0;
50875097

50885098
out_abort:
50895099
mdb_txn_abort(txn);
5090-
if (rc)
5091-
goto error;
5092-
return 0;
50935100

50945101
error:
50955102
database_readonly_lookup_finish();

src/tests/trustdb_lmdb_test.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,46 @@ static int test_lmdb_readonly_probe_does_not_break_live_env(void)
697697
return 0;
698698
}
699699

700+
/*
701+
* test_lmdb_readonly_lookup_keeps_dbi_valid - Guard CLI read-only lookups.
702+
*
703+
* Returns 0 when the DBI opened during read-only lookup setup remains usable
704+
* by later lookup transactions.
705+
*/
706+
static int test_lmdb_readonly_lookup_keeps_dbi_valid(void)
707+
{
708+
conf_t cfg;
709+
char dir[128];
710+
long entries = 0;
711+
int rc;
712+
const char *trusted_path = "/usr/bin/readonly-dbi";
713+
const char *digest =
714+
"abababababababababababababababababababababababababababababababab";
715+
char payload[512];
716+
717+
rc = with_temp_db(dir, sizeof(dir), &cfg);
718+
CHECK(rc == 0, 250, "[ERROR:250] failed to open temporary LMDB");
719+
720+
snprintf(payload, sizeof(payload), "%s " DATA_FORMAT "\n",
721+
trusted_path, SRC_FILE_DB, (size_t)789, digest);
722+
rc = import_records(payload, &entries);
723+
CHECK(rc == 0 && entries == 1, 251,
724+
"[ERROR:251] readonly lookup record import failed");
725+
726+
database_close_for_tests();
727+
728+
rc = database_readonly_lookup_start();
729+
CHECK(rc == 0, 252, "[ERROR:252] readonly lookup start failed");
730+
CHECK(check_trust_database_readonly(trusted_path, NULL, -1) == 1, 253,
731+
"[ERROR:253] readonly lookup could not read trusted path");
732+
733+
database_readonly_lookup_finish();
734+
database_set_location(NULL, NULL);
735+
CHECK(remove_lmdb_files(dir) == 0, 254,
736+
"[ERROR:254] readonly lookup cleanup failed");
737+
return 0;
738+
}
739+
700740
static int test_lmdb_chunked_import(void)
701741
{
702742
const unsigned int record_count = 4105;
@@ -1538,6 +1578,10 @@ int main(void)
15381578
if (rc)
15391579
return rc;
15401580

1581+
rc = test_lmdb_readonly_lookup_keeps_dbi_valid();
1582+
if (rc)
1583+
return rc;
1584+
15411585
rc = test_lmdb_chunked_import();
15421586
if (rc)
15431587
return rc;

0 commit comments

Comments
 (0)