Full_Name: Christopher Zimmermann Version: lmdb 0.9.24 OS: OpenBSD URL: ftp://ftp.openldap.org/incoming/ Submission from: (NULL) (85.212.180.240)
Hi,
I can reliably hit a Bus error on OpenBSD. This is triggered by OpenBSDs malloc/free junking [1] and a use-after-free bug in lmdb.
Steps to reproduce: - begin a read/write transaction (getting env->me_txn0) - fill the environment -> returns MDB_MAP_FULL -> sets txn->mt_flags |= MDB_TXN_ERROR; (This is also env->me_txn0 !) -> calls mdb_txn_abort -> calls mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE): mdb_txn_end tries not to free env->me_txn0:
} else if (!F_ISSET(txn->mt_flags, MDB_TXN_FINISHED)) { [...] txn->mt_flags = MDB_TXN_FINISHED; if (!txn->mt_parent) { [...] mdb.c:3020 mode = 0; /* txn == env->me_txn0, do not free() it */ [...] } [...] } if (mode & MDB_END_FREE) free(txn);
this prevents the free only for unfinished transactions. Unfinished transactions are now finished. - abort the transaction (again) with mdb_abort() -> calls mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE): since the env->me_txn0 detection is skipped on MDB_TXN_FINISHED transactions the transaction is freed, the memory will get "junked". - begin a read/write transaction (getting now invalid env->me_txn0) -> calls mdb_txn_renew0(env->me_txn0) MDB_env *env = txn->mt_env; /* txn->mt_env is now invalid */ MDB_txninfo *ti = env->me_txns; /* triggers bus error */
Please make the protection against freeing of me_txn0 more robust.
Thanks, Christopher Zimmermann