Details
-
Bug
-
Status: Open (View Workflow)
-
Minor
-
Resolution: Unresolved
-
13.2
-
None
-
None
-
Linux, ASAN+UBSAN debug build of main (c894d97781), GCC 11.5.0 (libasan.so.6), mtr
Description
In an ASAN build, TRASH_MEM() (TRASH_FREE(), that is MEM_NOACCESS()) poisons the unused part of a memory root block: alloc_root() does this for each new block and makes only the pieces it returns addressable again, so the redzones and the unused rest stay poisoned. For a memory root with ROOT_FLAG_VMEM (MY_ROOT_USE_VMEM, for example THD::user_vars_memroot since MDEV-40337), free_root() then returns the blocks with root_free(), which calls my_virtual_mem_release(), that is munmap(), without making them addressable again. The ASAN runtime we use (libasan.so.6 from GCC 11.5) keeps the poison in its shadow memory for that address range. When a later mmap() gets the same addresses, ASAN reports a use-after-poison on valid memory. (Newer ASAN runtimes may clear the shadow in their own munmap() interceptor; we did not try one.)
On an ASAN build of main,
./mtr innodb_fts.fulltext_left_join innodb_fts.fulltext_misc
|
fails in innodb_fts.fulltext_misc with a use-after-poison in __interceptor_memcpy at 0x7fcc33800020. The same run fails the same way on an ASAN build of our MDEV-10267 branch (main plus our patches, which do not change any file in this stack). There the statement is "SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)" and the stack is:
ERROR: AddressSanitizer: use-after-poison on address 0x77886a600020
|
READ of size 42 at 0x77886a600020 thread T12
|
#0 __interceptor_memcpy
|
#1 _ma_mmap_pread storage/maria/ma_dynrec.c:143
|
#2 _ma_read_static_record storage/maria/ma_statrec.c:190
|
#3 _ma_read_rnd_static_record storage/maria/ma_statrec.c:278
|
#4 maria_scan storage/maria/ma_scan.c:55
|
#5 ha_maria::rnd_next(unsigned char*) storage/maria/ha_maria.cc:2647
|
Address 0x77886a600020 is a wild pointer.
|
Each test passes when it runs alone. In parallel innodb_fts runs it depends on which tests a worker ran before: two parallel runs on main did not show it, two on the branch build (which has a few more innodb_fts tests) did, and one of them also had the same kind of report for INSTALL PLUGIN simple_parser in innodb_fts.plugin_debug, on a global variable of mypluglib.so that had been loaded at such an address:
ERROR: AddressSanitizer: use-after-poison on address 0x7f94721e77c0
|
WRITE of size 8 at 0x7f94721e77c0 thread T12
|
#0 my_getopt_init_one_value mysys/my_getopt.c:1408
|
#1 init_variables mysys/my_getopt.c:1531
|
#2 handle_options mysys/my_getopt.c:282
|
#3 test_plugin_options sql/sql_plugin.cc:4366
|
0x7f94721e77c0 is located 0 bytes inside of global variable 'sysvar_one_value' defined in 'plugin/fulltext/plugin_example.c:222:17'
|
With
@@ static void root_free(MEM_ROOT *root, void *ptr, size_t size) |
update_malloc_size(-(longlong) size,
|
MY_TEST(root->flags & ROOT_FLAG_THREAD_SPECIFIC));
|
+ MEM_MAKE_ADDRESSABLE(ptr, size);
|
my_virtual_mem_release(ptr, size);
|
the two-test run above passes on main, and on the branch build two parallel runs of the innodb_fts suite show no use-after-poison (only the UBSAN reports in innodb_fts.stopword that are there without this change too). The same could be done in my_virtual_mem_release() itself.
MDEV-41029 also shows a use-after-poison when a plugin is installed, but that is a different bug: there ignore_db_dirs_append() calls my_free() on the value of the READ_ONLY variable ignore_db_dirs, which since MDEV-40341 is a copy in read_only_root and was not allocated with my_malloc().
We ran into this while testing fixes for MDEV-10267 in an ASAN build.
Attachments
Issue Links
- relates to
-
MDEV-40337 store user vars in a dedicated memroot
-
- Closed
-
-
MDEV-41029 AddressSanitizer: use-after-poison - "install soname ha_rocksdb"
-
- Open
-