[MDEV-30942] MSAN_OPTIONS=poison_in_dtor=1 causes failures in free_root() Created: 2023-03-28  Updated: 2023-11-28

Status: Open
Project: MariaDB Server
Component/s: Server, Stored routines
Affects Version/s: 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.11, 11.0, 11.1
Fix Version/s: 10.5, 10.6, 10.11, 11.0, 11.1

Type: Bug Priority: Major
Reporter: Marko Mäkelä Assignee: Oleksandr Byelkin
Resolution: Unresolved Votes: 0
Labels: MSAN

Issue Links:
Relates
relates to MDEV-20377 Make WITH_MSAN more usable Closed
relates to MDEV-30936 clang 15.0.7 -fsanitize=memory fails ... Closed

 Description   

Recently, MSAN_OPTIONS=poison_in_dtor=1 was enabled by default. This caught some foul play in InnoDB (to be fixed in MDEV-30936) as well as massive amounts of failures in free_root(), because the root->used or root->free lists could be marked as uninitialized in various destructors for objects that are allocated from a MEM_ROOT.

It would be good programming style to make sure that MemorySanitizer does not report any errors when MSAN_OPTIONS=poison_in_dtor=1 is set.

It is possible to work around the errors with the following patch:

diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index aa0182c755e..b9071ad7eee 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -415,14 +415,26 @@ void free_root(MEM_ROOT *root, myf MyFlags)
   if (!(MyFlags & MY_KEEP_PREALLOC))
     root->pre_alloc=0;
 
+#if __has_feature(memory_sanitizer)
+  /* Work around MSAN_OPTIONS=poison_in_dtor=1 */
+  MEM_MAKE_DEFINED(&root->used, sizeof root->used);
+  MEM_MAKE_DEFINED(&root->free, sizeof root->free);
+#endif
+
   for (next=root->used; next ;)
   {
+#if __has_feature(memory_sanitizer)
+    MEM_MAKE_DEFINED(&next->next, sizeof next->next);
+#endif
     old=next; next= next->next ;
     if (old != root->pre_alloc)
       my_free(old);
   }
   for (next=root->free ; next ;)
   {
+#if __has_feature(memory_sanitizer)
+    MEM_MAKE_DEFINED(&next->next, sizeof next->next);
+#endif
     old=next; next= next->next;
     if (old != root->pre_alloc)
       my_free(old);

I think that explicitly setting MSAN_OPTIONS=poison_in_dtor=0 when using Clang 15 or later is a lesser evil. The above patch could mask other errors as well.



 Comments   
Comment by Marko Mäkelä [ 2023-03-28 ]

With a proper MSAN_SYMBOLIZER_PATH wrapper script (see MDEV-30936), we can get nice traces:

10.5 402f36dd652b57a48d2d3e18949f5d7a1450363d

==2878081==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x557ba37746de in free_root /mariadb/10.5/mysys/my_alloc.c:418:3
    #1 0x557ba12cb046 in Server_side_cursor::operator delete(void*, unsigned long) /mariadb/10.5/sql/sql_cursor.cc:216:3
    #2 0x557ba12cb046 in Materialized_cursor::~Materialized_cursor() /mariadb/10.5/sql/sql_cursor.cc:396:1
    #3 0x557ba0f49607 in sp_cursor::destroy() /mariadb/10.5/sql/sp_rcontext.cc:783:3
    #4 0x557ba0f49607 in sp_cursor::close(THD*) /mariadb/10.5/sql/sp_rcontext.cc:776:3
    #5 0x557ba0f27ca4 in sp_instr_cclose::execute(THD*, unsigned int*) /mariadb/10.5/sql/sp_head.cc:4561:13
    #6 0x557ba0efa7b4 in sp_head::execute(THD*, bool) /mariadb/10.5/sql/sp_head.cc:1438:20
    #7 0x557ba0f033c6 in sp_head::execute_procedure(THD*, List<Item>*) /mariadb/10.5/sql/sp_head.cc:2450:5
    #8 0x557ba144caf3 in do_execute_sp(THD*, sp_head*) /mariadb/10.5/sql/sql_parse.cc:3089:16
    #9 0x557ba144bdc4 in Sql_cmd_call::execute(THD*) /mariadb/10.5/sql/sql_parse.cc:3335:9
    #10 0x557ba1452955 in mysql_execute_command(THD*) /mariadb/10.5/sql/sql_parse.cc:6061:26
    #11 0x557ba143bb06 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /mariadb/10.5/sql/sql_parse.cc:8091:18
    #12 0x557ba14311ec in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /mariadb/10.5/sql/sql_parse.cc:1891:7
    #13 0x557ba143d208 in do_command(THD*) /mariadb/10.5/sql/sql_parse.cc:1375:17
    #14 0x557ba1aa472e in do_handle_one_connection(CONNECT*, bool) /mariadb/10.5/sql/sql_connect.cc:1416:11
    #15 0x557ba1aa3e47 in handle_one_connection /mariadb/10.5/sql/sql_connect.cc:1318:5
    #16 0x557ba22fe547 in pfs_spawn_thread /mariadb/10.5/storage/perfschema/pfs.cc:2201:3
    #17 0x7f4934887fd3 in start_thread nptl/pthread_create.c:442:8
    #18 0x7f493490866b in clone3 misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
 
  Uninitialized value was stored to memory at
    #0 0x557ba055cec9 in __msan_memcpy (/dev/shm/10.5msan/sql/mariadbd+0xfc7ec9) (BuildId: 54a87c1c8e383aaa)
    #1 0x557ba12cafff in Server_side_cursor::operator delete(void*, unsigned long) /mariadb/10.5/sql/sql_cursor.cc:206:22
    #2 0x557ba12cafff in Materialized_cursor::~Materialized_cursor() /mariadb/10.5/sql/sql_cursor.cc:396:1
 
  Memory was marked as uninitialized
    #0 0x557ba0563cfd in __sanitizer_dtor_callback (/dev/shm/10.5msan/sql/mariadbd+0xfcecfd) (BuildId: 54a87c1c8e383aaa)
    #1 0x557ba12caf0d in Materialized_cursor::~Materialized_cursor() /mariadb/10.5/sql/sql_cursor.cc:399:1

Generated at Thu Feb 08 10:20:04 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.