Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-24053

MSAN use-of-uninitialized-value in tpool::simulated_aio::simulated_aio_callback()

Details

    Description

      A change in MDEV-23855 introduced a regression for MemorySanitizer: the doublewrite buffer would write uninitialized data to the file.

      I did not find out why exactly that commit introduced the failure, but the fix is simple:

      diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
      index a8ae3e2782a..c14634ae229 100644
      --- a/storage/innobase/buf/buf0dblwr.cc
      +++ b/storage/innobase/buf/buf0dblwr.cc
      @@ -736,7 +736,8 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
         encryption and/or page compression */
         void *frame= buf_page_get_frame(request.bpage);
       
      -  memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(p, frame, size);
      +  memcpy_aligned<256>(p, frame, size); /* fil_page_compress() guarantee */
      +  memset_aligned<256>(p + size, 0, srv_page_size - size);
         ut_ad(!request.bpage->zip_size() || request.bpage->zip_size() == size);
         ut_ad(active_slot->reserved == active_slot->first_free);
         ut_ad(active_slot->reserved < buf_size);
      

      This is also correcting the alignment assertion. fil_page_compress() for page_compressed pages is only guaranteeing 256-byte alignment, not 512 bytes. For ROW_FORMAT=COMPRESSED pages, the minimum alignment is 1024 bytes.

      Attachments

        Issue Links

          Activity

            It turns out that the alignment assumptions in memcpy_aligned and memset_aligned do not cover the size, but only the pointers. Hence, the 512-byte alignment of the existing call is not incorrect, but only inaccurate. I would propose an improved patch:

            diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
            index a8ae3e2782a..284936ddc43 100644
            --- a/storage/innobase/buf/buf0dblwr.cc
            +++ b/storage/innobase/buf/buf0dblwr.cc
            @@ -736,7 +736,11 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
               encryption and/or page compression */
               void *frame= buf_page_get_frame(request.bpage);
             
            -  memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(p, frame, size);
            +  /* "frame" is at least 1024-byte aligned for ROW_FORMAT=COMPRESSED pages,
            +  and at least srv_page_size (4096-byte) for everything else. */
            +  memcpy_aligned<UNIV_ZIP_SIZE_MIN>(p, frame, size);
            +  /* fil_page_compress() for page_compressed guarantees 256-byte alignment */
            +  memset_aligned<256>(p + size, 0, srv_page_size - size);
               ut_ad(!request.bpage->zip_size() || request.bpage->zip_size() == size);
               ut_ad(active_slot->reserved == active_slot->first_free);
               ut_ad(active_slot->reserved < buf_size);
            

            marko Marko Mäkelä added a comment - It turns out that the alignment assumptions in memcpy_aligned and memset_aligned do not cover the size, but only the pointers. Hence, the 512-byte alignment of the existing call is not incorrect, but only inaccurate. I would propose an improved patch: diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index a8ae3e2782a..284936ddc43 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -736,7 +736,11 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size) encryption and/or page compression */ void *frame= buf_page_get_frame(request.bpage); - memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(p, frame, size); + /* "frame" is at least 1024-byte aligned for ROW_FORMAT=COMPRESSED pages, + and at least srv_page_size (4096-byte) for everything else. */ + memcpy_aligned<UNIV_ZIP_SIZE_MIN>(p, frame, size); + /* fil_page_compress() for page_compressed guarantees 256-byte alignment */ + memset_aligned<256>(p + size, 0, srv_page_size - size); ut_ad(!request.bpage->zip_size() || request.bpage->zip_size() == size); ut_ad(active_slot->reserved == active_slot->first_free); ut_ad(active_slot->reserved < buf_size);

            People

              marko Marko Mäkelä
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.