Loading...
Loading...
[It seems unlikely this issue can reproduce in practice - it's mainly an issue for tests] Context: collMod can convert a non-unique index to unique, this is done in multiple steps. User runs collMod(coll, prepareUnique:true). This prevents insertion of new duplicates. User runs collMod(coll, unique:true). collMod takes an IX lock and scans the index to ensure it has no pre-existing duplicates. collMod releases the IX lock collMod takes an X lock and marks the index as unique. collMod ensures that in between (2.1) and (2.3) the index does not change by: In (2.1), under the IX lock it saves a pointer to the index descriptor. In (2.3), under the X lock it compares that pointer to the current index descriptor pointer. Issue: After the IX lock is released in (2.2), the index can be dropped, when that happens the saved index descriptor pointer becomes dangling. This can not cause a crash since the pointer is never dereferenced but rather the issue is that the later pointer comparison is susceptible to the ABA problem. I.e. collMod may incorrectly think the index has not changed so it will convert it to unique even though it may contain duplicates. The unlikely interleaving is as follows: User runs collMod(coll, {a: 1}, prepareUnique:true). This prevents insertion of new duplicates on field "a". User runs collMod(coll, {a: 1}, unique:true). collMod takes an IX lock and scans the index to ensure it has no pre-existing duplicates on field "a". collMod releases the IX lock User runs dropIndex(coll, {a: 1}) User runs createIndex(coll, {a: 1}) It happens that the descriptor for the new index on {a: 1} lands on the same pointer as the old index on {a: 1} User inserts duplicates e.g. insertMany(coll, {a: 123}, {a: 123}) User runs collMod(coll, {a: 1}, prepareUnique:true) collMod takes an X lock and marks the index as unique. It will incorrectly consider that the index it scanned in (2.1) has not changed since the pointer to the index descriptor is identical. Burning in the attached jstest will reproduce the issue. Solution: collMod should keep the index descriptor alive in between (2.1) and (2.3), it can do this by holding a shared_ptr to its IndexCatalogEntry.
MongoDB Integration
Learn more about where this data comes from
Bug Scrub Advisor
Streamline upgrades with automated vendor bug scrubs
BugZero Enterprise
Wish you caught this bug sooner? Get proactive today.