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
[1]
https://man.openbsd.org/malloc#j