mdbx: устранение возможности `SIGSEGV` внутри `coherency_check()`.

Падение происходило в случае когда:

 - Некоторый процесс увеличивал размер БД с изменением геометрии (с
   увеличением предельного размера БД и её отображения в ОЗУ), затем
   задействовал страницу из добавленного сегмента в качестве корневой для
   FreeDB/GC и/или MainDB и фиксировал транзакцию.

 - Другой процесс, уже работавший с БД до изменения геометрии первым
   процессом, запускал транзакцию чтения. Падение происходило при проверке
   «когерентности» отображения страниц БД в ОЗУ, при проверке отметок
   модификации внутри корневых страниц, так как в этом случае они были вне
   границ текущего отображения БД в адресном пространстве этого процесса.

Похоже что в ходе какого-то рефакторинга потерялась соответствующая
проверка. Этот коммит добавляет её как временное решение, до переноса
проверки «когерентности» после изменения размера отображения (добавлено в
TODO).
This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2024-08-07 17:38:53 +03:00
parent 7bff3b3df6
commit edfa526138
2 changed files with 11 additions and 2 deletions

View File

@ -11,6 +11,7 @@ For the same reason ~~Github~~ is blacklisted forever.
So currently most of the links are broken due to noted malicious ~~Github~~ sabotage.
- Внутри `txn_renew()` вынести проверку когерентности mmap за/после изменение размера.
- [Migration guide from LMDB to MDBX](https://libmdbx.dqdkfa.ru/dead-github/issues/199).
- [Support for RAW devices](https://libmdbx.dqdkfa.ru/dead-github/issues/124).
- [Support MessagePack for Keys & Values](https://libmdbx.dqdkfa.ru/dead-github/issues/115).

View File

@ -76,7 +76,13 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid,
: "(wagering meta)");
ok = false;
}
if (likely(freedb_root && freedb_mod_txnid)) {
/* Проверяем отметки внутри корневых страниц только если сами страницы
* в пределах текущего отображения. Иначе возможны SIGSEGV до переноса
* вызова coherency_check_head() после dxb_resize() внутри txn_renew(). */
if (likely(freedb_root && freedb_mod_txnid &&
(size_t)ptr_dist(env->dxb_mmap.base, freedb_root) <
env->dxb_mmap.limit)) {
VALGRIND_MAKE_MEM_DEFINED(freedb_root, sizeof(freedb_root->txnid));
MDBX_ASAN_UNPOISON_MEMORY_REGION(freedb_root, sizeof(freedb_root->txnid));
const txnid_t root_txnid = freedb_root->txnid;
@ -91,7 +97,9 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid,
ok = false;
}
}
if (likely(maindb_root && maindb_mod_txnid)) {
if (likely(maindb_root && maindb_mod_txnid &&
(size_t)ptr_dist(env->dxb_mmap.base, maindb_root) <
env->dxb_mmap.limit)) {
VALGRIND_MAKE_MEM_DEFINED(maindb_root, sizeof(maindb_root->txnid));
MDBX_ASAN_UNPOISON_MEMORY_REGION(maindb_root, sizeof(maindb_root->txnid));
const txnid_t root_txnid = maindb_root->txnid;