[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
(ITS#8424) mdb_env_cwalk() is broken, leading to crash if MDB_CP_COMPACT is set
- To: openldap-its@OpenLDAP.org
- Subject: (ITS#8424) mdb_env_cwalk() is broken, leading to crash if MDB_CP_COMPACT is set
- From: ddmitrie@gmail.com
- Date: Sat, 14 May 2016 15:34:19 +0000
- Auto-submitted: auto-generated (OpenLDAP-ITS)
Full_Name: Dmitry Dmitrienko
Version: trunk, 0.9.18
OS: Linux, Windows
URL:
Submission from: (NULL) (100.36.101.84)
In short:
Reproduce: create a large database (1GB would be enough), run md_copy with -c
argument. Expected result - compacted new database, Actual result - empty new
database and crash in md_copy.
In details:
mdb_env_cwalk() defines cursor and does not initialize most of its fields,
including mc_flags field. Then it calls mdb_page_get() procedure, which checks
if (C_ORIG_RDONLY|C_WRITEMAP) flags are set in mc_flags. Since this field is not
initialized, it may have arbitrary value. If these flags are not set, it starts
checking txn's mt_u.dirty_list, as if it was a writing transaction, while in
fact this is a walker, it is a reader, so it initialized mt_u.reader fields.
This field is in the same memory location with dirty_list just because it's
union. So mdb_page_get() actually reads lock file memory (it's where mt_u.reader
points to). If the database is large enough, it leads to access to far beyond
lock file memory mapped region and crashes md_copy.
Proposed fix:
mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
...
+ memset(&mc, 0, sizeof(mc));
mc.mc_snum = 1;
mc.mc_top = 0;
mc.mc_txn = my->mc_txn;
+ mc.mc.mc_flags = my->mc_txn->mt_flags & (C_ORIG_RDONLY|C_WRITEMAP);