Skip to content

Commit 554c60a

Browse files
author
Jan Lindström
committed
MDEV-11182: InnoDB: Assertion failure in file buf0buf.cc line 4730 (encryption.create_or_replace fails in buildbot and outside)
Analysis: Problem is that page is encrypted but encryption information on page 0 has already being changed. Fix: If page header contains key_version != 0 and even if based on current encryption information tablespace is not encrypted we need to check is page corrupted. If it is not, then we know that page is not encrypted. If page is corrupted, we need to try to decrypt it and then compare the stored and calculated checksums to see is page corrupted or not.
1 parent cb5685a commit 554c60a

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

storage/innobase/buf/buf0buf.cc

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ Created 11/5/1995 Heikki Tuuri
6868
#include "lzo/lzo1x.h"
6969
#endif
7070

71+
/* Enable this for checksum error messages. */
72+
//#ifdef UNIV_DEBUG
73+
//#define UNIV_DEBUG_LEVEL2 1
74+
//#endif
75+
7176
/*
7277
IMPLEMENTATION OF THE BUFFER POOL
7378
=================================
@@ -533,7 +538,7 @@ buf_page_is_checksum_valid_crc32(
533538
if (!(checksum_field1 == crc32 && checksum_field2 == crc32)) {
534539
ib_logf(IB_LOG_LEVEL_INFO,
535540
"Page checksum crc32 not valid field1 %lu field2 %lu crc32 %lu.",
536-
checksum_field1, checksum_field2, crc32);
541+
checksum_field1, checksum_field2, (ulint)crc32);
537542
}
538543
#endif
539544

@@ -584,7 +589,7 @@ buf_page_is_checksum_valid_innodb(
584589
#ifdef UNIV_DEBUG_LEVEL2
585590
ib_logf(IB_LOG_LEVEL_INFO,
586591
"Page checksum innodb not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
587-
checksum_field1, checksum_field2, buf_calc_page_old_checksum(read_buf),
592+
checksum_field1, checksum_field2, buf_calc_page_new_checksum(read_buf),
588593
mach_read_from_4(read_buf + FIL_PAGE_LSN)
589594
);
590595
#endif
@@ -610,7 +615,7 @@ buf_page_is_checksum_valid_none(
610615
if (!(checksum_field1 == checksum_field2 || checksum_field1 == BUF_NO_CHECKSUM_MAGIC)) {
611616
ib_logf(IB_LOG_LEVEL_INFO,
612617
"Page checksum none not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
613-
checksum_field1, checksum_field2, buf_calc_page_old_checksum(read_buf),
618+
checksum_field1, checksum_field2, BUF_NO_CHECKSUM_MAGIC,
614619
mach_read_from_4(read_buf + FIL_PAGE_LSN)
615620
);
616621
}
@@ -707,6 +712,7 @@ buf_page_is_corrupted(
707712
if (zip_size) {
708713
return(!page_zip_verify_checksum(read_buf, zip_size));
709714
}
715+
710716
if (page_encrypted) {
711717
return (FALSE);
712718
}
@@ -1970,6 +1976,11 @@ buf_pool_watch_set(
19701976
buf_pool->watch[]. However, it is not in the critical code path
19711977
as this function will be called only by the purge thread. */
19721978

1979+
/* Enable this for checksum error messages. Currently on by
1980+
default on UNIV_DEBUG for encryption bugs. */
1981+
#ifdef UNIV_DEBUG
1982+
#define UNIV_DEBUG_LEVEL2 1
1983+
#endif
19731984

19741985
/* To obey latching order first release the hash_lock. */
19751986
rw_lock_x_unlock(hash_lock);
@@ -4490,7 +4501,7 @@ buf_page_check_corrupt(
44904501
((buf_block_t*) bpage)->frame;
44914502
bool page_compressed = bpage->page_encrypted;
44924503
ulint stored_checksum = bpage->stored_checksum;
4493-
ulint calculated_checksum = bpage->stored_checksum;
4504+
ulint calculated_checksum = bpage->calculated_checksum;
44944505
bool page_compressed_encrypted = bpage->page_compressed;
44954506
ulint space_id = mach_read_from_4(
44964507
dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
@@ -4596,6 +4607,10 @@ buf_page_io_complete(
45964607
frame = ((buf_block_t*) bpage)->frame;
45974608
}
45984609

4610+
ib_logf(IB_LOG_LEVEL_INFO,
4611+
"Page %u in tablespace %u encryption error key_version %u.",
4612+
bpage->offset, bpage->space, bpage->key_version);
4613+
45994614
goto database_corrupted;
46004615
}
46014616

@@ -4607,6 +4622,11 @@ buf_page_io_complete(
46074622
FALSE)) {
46084623

46094624
buf_pool->n_pend_unzip--;
4625+
4626+
ib_logf(IB_LOG_LEVEL_INFO,
4627+
"Page %u in tablespace %u zip_decompress failure.",
4628+
bpage->offset, bpage->space);
4629+
46104630
goto database_corrupted;
46114631
}
46124632
buf_pool->n_pend_unzip--;
@@ -6245,7 +6265,23 @@ buf_page_decrypt_after_read(
62456265
(crypt_data &&
62466266
crypt_data->type == CRYPT_SCHEME_UNENCRYPTED &&
62476267
key_version != 0)) {
6248-
key_version = 0;
6268+
byte* frame = NULL;
6269+
6270+
if (buf_page_get_zip_size(bpage)) {
6271+
frame = bpage->zip.data;
6272+
} else {
6273+
frame = ((buf_block_t*) bpage)->frame;
6274+
}
6275+
6276+
/* If page is not corrupted at this point, page can't be
6277+
encrypted, thus set key_version to 0. If page is corrupted,
6278+
we assume at this point that it is encrypted as page
6279+
contained key_version != 0. Note that page could still be
6280+
really corrupted. This we will find out after decrypt by
6281+
checking page checksums. */
6282+
if (!buf_page_is_corrupted(false, frame, buf_page_get_zip_size(bpage))) {
6283+
key_version = 0;
6284+
}
62496285
}
62506286

62516287
/* If page is encrypted read post-encryption checksum */

storage/xtradb/buf/buf0buf.cc

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ Created 11/5/1995 Heikki Tuuri
6565
#include "fil0pagecompress.h"
6666
#include "ha_prototypes.h"
6767

68+
/* Enable this for checksum error messages. */
69+
//#ifdef UNIV_DEBUG
70+
//#define UNIV_DEBUG_LEVEL2 1
71+
//#endif
6872

6973
/* prototypes for new functions added to ha_innodb.cc */
7074
trx_t* innobase_get_trx();
@@ -599,7 +603,7 @@ buf_page_is_checksum_valid_crc32(
599603
if (!(checksum_field1 == crc32 && checksum_field2 == crc32)) {
600604
ib_logf(IB_LOG_LEVEL_INFO,
601605
"Page checksum crc32 not valid field1 %lu field2 %lu crc32 %lu.",
602-
checksum_field1, checksum_field2, crc32);
606+
checksum_field1, checksum_field2, (ulint)crc32);
603607
}
604608
#endif
605609

@@ -650,7 +654,7 @@ buf_page_is_checksum_valid_innodb(
650654
#ifdef UNIV_DEBUG_LEVEL2
651655
ib_logf(IB_LOG_LEVEL_INFO,
652656
"Page checksum innodb not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
653-
checksum_field1, checksum_field2, buf_calc_page_old_checksum(read_buf),
657+
checksum_field1, checksum_field2, buf_calc_page_new_checksum(read_buf),
654658
mach_read_from_4(read_buf + FIL_PAGE_LSN)
655659
);
656660
#endif
@@ -676,7 +680,7 @@ buf_page_is_checksum_valid_none(
676680
if (!(checksum_field1 == checksum_field2 || checksum_field1 == BUF_NO_CHECKSUM_MAGIC)) {
677681
ib_logf(IB_LOG_LEVEL_INFO,
678682
"Page checksum none not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
679-
checksum_field1, checksum_field2, buf_calc_page_old_checksum(read_buf),
683+
checksum_field1, checksum_field2, BUF_NO_CHECKSUM_MAGIC,
680684
mach_read_from_4(read_buf + FIL_PAGE_LSN)
681685
);
682686
}
@@ -773,6 +777,7 @@ buf_page_is_corrupted(
773777
if (zip_size) {
774778
return(!page_zip_verify_checksum(read_buf, zip_size));
775779
}
780+
776781
if (page_encrypted) {
777782
return (FALSE);
778783
}
@@ -4603,7 +4608,7 @@ buf_page_check_corrupt(
46034608
((buf_block_t*) bpage)->frame;
46044609
bool page_compressed = bpage->page_encrypted;
46054610
ulint stored_checksum = bpage->stored_checksum;
4606-
ulint calculated_checksum = bpage->stored_checksum;
4611+
ulint calculated_checksum = bpage->calculated_checksum;
46074612
bool page_compressed_encrypted = bpage->page_compressed;
46084613
ulint space_id = mach_read_from_4(
46094614
dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
@@ -4707,6 +4712,10 @@ buf_page_io_complete(
47074712
frame = ((buf_block_t*) bpage)->frame;
47084713
}
47094714

4715+
ib_logf(IB_LOG_LEVEL_INFO,
4716+
"Page %u in tablespace %u encryption error key_version %u.",
4717+
bpage->offset, bpage->space, bpage->key_version);
4718+
47104719
goto database_corrupted;
47114720
}
47124721

@@ -4720,6 +4729,10 @@ buf_page_io_complete(
47204729
os_atomic_decrement_ulint(
47214730
&buf_pool->n_pend_unzip, 1);
47224731

4732+
ib_logf(IB_LOG_LEVEL_INFO,
4733+
"Page %u in tablespace %u zip_decompress failure.",
4734+
bpage->offset, bpage->space);
4735+
47234736
goto database_corrupted;
47244737
}
47254738
os_atomic_decrement_ulint(&buf_pool->n_pend_unzip, 1);
@@ -6440,7 +6453,23 @@ buf_page_decrypt_after_read(
64406453
(crypt_data &&
64416454
crypt_data->type == CRYPT_SCHEME_UNENCRYPTED &&
64426455
key_version != 0)) {
6443-
key_version = 0;
6456+
byte* frame = NULL;
6457+
6458+
if (buf_page_get_zip_size(bpage)) {
6459+
frame = bpage->zip.data;
6460+
} else {
6461+
frame = ((buf_block_t*) bpage)->frame;
6462+
}
6463+
6464+
/* If page is not corrupted at this point, page can't be
6465+
encrypted, thus set key_version to 0. If page is corrupted,
6466+
we assume at this point that it is encrypted as page
6467+
contained key_version != 0. Note that page could still be
6468+
really corrupted. This we will find out after decrypt by
6469+
checking page checksums. */
6470+
if (!buf_page_is_corrupted(false, frame, buf_page_get_zip_size(bpage))) {
6471+
key_version = 0;
6472+
}
64446473
}
64456474

64466475
/* If page is encrypted read post-encryption checksum */

0 commit comments

Comments
 (0)