From 7772c7cd945cf674b212b82f4d156099c67344a2 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 14 Aug 2019 12:01:40 +0530 Subject: [PATCH] MDEV-20340 Encrypted temporary tables cannot be read with full_crc32 Problem: ======== Checksum for the encrypted temporary tablespace is not stored in the page for full crc32 format. Solution: ======== Made temporary tablespace in full crc32 format irrespective of encryption parameter. buf_tmp_page_encrypt(), buf_tmp_page_decrypt() - Both follows full_crc32 format. --- ...nodb_encrypt_temporary_tables.combinations | 5 +++ storage/innobase/buf/buf0buf.cc | 37 ++++++++----------- storage/innobase/handler/ha_innodb.cc | 12 ++---- 3 files changed, 24 insertions(+), 30 deletions(-) create mode 100644 mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.combinations diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.combinations b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.combinations new file mode 100644 index 00000000000..729380593f3 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.combinations @@ -0,0 +1,5 @@ +[strict_crc32] +--innodb-checksum-algorithm=strict_crc32 + +[strict_full_crc32] +--innodb-checksum-algorithm=strict_full_crc32 diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 0701ec31f5f..86b669209cb 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -484,7 +484,7 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) } /* read space & lsn */ - uint header_len = FIL_PAGE_DATA; + uint header_len = FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; /* Copy FIL page header, it is not encrypted */ memcpy(tmp_frame, src_frame, header_len); @@ -493,7 +493,7 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) const byte* src = src_frame + header_len; byte* dst = tmp_frame + header_len; uint srclen = uint(srv_page_size) - - header_len - FIL_PAGE_DATA_END; + - (header_len + FIL_PAGE_FCRC32_CHECKSUM); ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET); if (!log_tmp_block_decrypt(src, srclen, dst, @@ -501,9 +501,9 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) return false; } - memcpy(tmp_frame + srv_page_size - FIL_PAGE_DATA_END, - src_frame + srv_page_size - FIL_PAGE_DATA_END, - FIL_PAGE_DATA_END); + memcpy(tmp_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM, + src_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM, + FIL_PAGE_FCRC32_CHECKSUM); memcpy(src_frame, tmp_frame, srv_page_size); srv_stats.pages_decrypted.inc(); @@ -5976,13 +5976,15 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) && !bpage->encrypted && fil_space_verify_crypt_checksum(dst_frame, bpage->zip_size()); + ut_ad(space->purpose != FIL_TYPE_TEMPORARY || space->full_crc32()); if (!still_encrypted) { /* If traditional checksums match, we assume that page is not anymore encrypted. */ if (space->full_crc32() && !buf_page_is_zeroes(dst_frame, space->physical_size()) - && (key_version || space->is_compressed())) { + && (key_version || space->is_compressed() + || space->purpose == FIL_TYPE_TEMPORARY)) { corrupted = buf_page_full_crc32_is_corrupted( space->id, dst_frame, space->is_compressed()); @@ -7427,28 +7429,21 @@ static byte* buf_tmp_page_encrypt( byte* src_frame, byte* dst_frame) { - uint header_len = FIL_PAGE_DATA; - /* FIL page header is not encrypted */ - memcpy(dst_frame, src_frame, header_len); - /* Calculate the start offset in a page */ - uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END; - uint srclen = srv_page_size - unencrypted_bytes; - const byte* src = src_frame + header_len; - byte* dst = dst_frame + header_len; + uint srclen = srv_page_size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + + FIL_PAGE_FCRC32_CHECKSUM); + const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; + byte* dst = dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; + + memcpy(dst_frame, src_frame, FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); if (!log_tmp_block_encrypt(src, srclen, dst, (offset * srv_page_size), true)) { return NULL; } - memcpy(dst_frame + srv_page_size - FIL_PAGE_DATA_END, - src_frame + srv_page_size - FIL_PAGE_DATA_END, - FIL_PAGE_DATA_END); - - /* Handle post encryption checksum */ - mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, - buf_calc_page_crc32(dst_frame)); + const ulint payload = srv_page_size - FIL_PAGE_FCRC32_CHECKSUM; + mach_write_to_4(dst_frame + payload, ut_crc32(dst_frame, payload)); srv_stats.pages_encrypted.inc(); srv_stats.n_temp_blocks_encrypted.inc(); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7b0ddceca0d..aa2f3805bd6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3876,15 +3876,9 @@ static int innodb_init_params() srv_tmp_space.set_name("innodb_temporary"); srv_tmp_space.set_path(srv_data_home); - switch (srv_checksum_algorithm) { - case SRV_CHECKSUM_ALGORITHM_FULL_CRC32: - case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32: - srv_tmp_space.set_flags(FSP_FLAGS_FCRC32_MASK_MARKER - | FSP_FLAGS_FCRC32_PAGE_SSIZE()); - break; - default: - srv_tmp_space.set_flags(FSP_FLAGS_PAGE_SSIZE()); - } + /* Temporary tablespace is in full crc32 format. */ + srv_tmp_space.set_flags(FSP_FLAGS_FCRC32_MASK_MARKER + | FSP_FLAGS_FCRC32_PAGE_SSIZE()); if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { ib::error() << "Unable to parse innodb_temp_data_file_path="