diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-10-10 15:19:44 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-10-10 15:24:14 +0300 |
commit | 0f7732d1d1d898f1a9051858932c18bcc9d6f2b4 (patch) | |
tree | d6d2e5e8c667e78a2302a1097ce955b7cb632c77 | |
parent | c11e5cdd12a6ffbc3c95e0abff6cc86920d592fa (diff) | |
download | mariadb-git-0f7732d1d1d898f1a9051858932c18bcc9d6f2b4.tar.gz |
MDEV-19335 adjustment for innodb_checksum_algorithm=full_crc32
When MDEV-12026 introduced innodb_checksum_algorithm=full_crc32 in
MariaDB 10.4, it accidentally added a dependency on buf_page_t::encrypted.
Now that the flag has been removed, we must adjust the page-read routine.
buf_page_io_complete(): When the full_crc32 page checksum matches but the
tablespace ID in the page does not match after decrypting, we should
declare it a decryption failure and suppress the page dump output and
any attempts to re-read the page.
11 files changed, 45 insertions, 7 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change.result b/mysql-test/suite/encryption/r/innodb-bad-key-change.result index 45c32317557..255dde207ed 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change.result @@ -6,6 +6,7 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9] call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1"); call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted"); call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found"); +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); # Start server with keys2.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt SET GLOBAL innodb_file_per_table = ON; diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result index 78b9b7854de..543c3bc29b2 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result @@ -6,6 +6,7 @@ call mtr.add_suppression("InnoDB: Tablespace for table \`test\`.\`t1\` is set as call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted"); call mtr.add_suppression("InnoDB: Cannot delete tablespace .* because it is not found in the tablespace memory cache"); call mtr.add_suppression("InnoDB: ALTER TABLE `test`\\.`t1` DISCARD TABLESPACE failed to find tablespace"); +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); # restart: --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result index 6c23f94eb47..e37ee8eb8cd 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result @@ -3,6 +3,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page n call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted"); +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); # restart: --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.combinations b/mysql-test/suite/encryption/t/innodb-bad-key-change.combinations new file mode 100644 index 00000000000..be3ecd67aa8 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.combinations @@ -0,0 +1,4 @@ +[crc32] +loose-innodb-checksum-algorithm=crc32 +[full_crc32] +loose-innodb-checksum-algorithm=full_crc32 diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.test b/mysql-test/suite/encryption/t/innodb-bad-key-change.test index 552b9867d69..a9a32a3d6fc 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.test @@ -16,6 +16,8 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9] call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1"); call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted"); call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found"); +# for innodb_checksum_algorithm=full_crc32 only +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); --echo # Start server with keys2.txt -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change2.combinations b/mysql-test/suite/encryption/t/innodb-bad-key-change2.combinations new file mode 100644 index 00000000000..be3ecd67aa8 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change2.combinations @@ -0,0 +1,4 @@ +[crc32] +loose-innodb-checksum-algorithm=crc32 +[full_crc32] +loose-innodb-checksum-algorithm=full_crc32 diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test index f100c330bad..bdbf2327e5d 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test @@ -17,6 +17,8 @@ call mtr.add_suppression("InnoDB: Tablespace for table \`test\`.\`t1\` is set as call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted"); call mtr.add_suppression("InnoDB: Cannot delete tablespace .* because it is not found in the tablespace memory cache"); call mtr.add_suppression("InnoDB: ALTER TABLE `test`\\.`t1` DISCARD TABLESPACE failed to find tablespace"); +# for innodb_checksum_algorithm=full_crc32 only +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); --let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt --source include/restart_mysqld.inc diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change3.combinations b/mysql-test/suite/encryption/t/innodb-bad-key-change3.combinations new file mode 100644 index 00000000000..be3ecd67aa8 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change3.combinations @@ -0,0 +1,4 @@ +[crc32] +loose-innodb-checksum-algorithm=crc32 +[full_crc32] +loose-innodb-checksum-algorithm=full_crc32 diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations b/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations new file mode 100644 index 00000000000..be3ecd67aa8 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations @@ -0,0 +1,4 @@ +[crc32] +loose-innodb-checksum-algorithm=crc32 +[full_crc32] +loose-innodb-checksum-algorithm=full_crc32 diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test index d2f75a3d6c1..b341fc81d39 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test @@ -13,6 +13,8 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9] # Suppression for builds where file_key_management plugin is linked statically call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted"); +# for innodb_checksum_algorithm=full_crc32 only +call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); --let $restart_parameters=--plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt --source include/restart_mysqld.inc diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index fa6a33662ad..7f00b27df0e 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5955,7 +5955,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) not decrypted and it could be either encrypted and corrupted or corrupted or good page. If we decrypted, there page could still be corrupted if used key does not match. */ - const bool seems_encrypted = (!space->full_crc32() && key_version) + const bool seems_encrypted = !space->full_crc32() && key_version && space->crypt_data && space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED; ut_ad(space->purpose != FIL_TYPE_TEMPORARY || space->full_crc32()); @@ -5970,7 +5970,6 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) space->id, dst_frame, space->is_compressed())) { err = DB_PAGE_CORRUPTED; } - } else if (buf_page_is_corrupted(true, dst_frame, space->flags)) { err = DB_PAGE_CORRUPTED; } @@ -6085,13 +6084,26 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict) } else if (read_space_id == 0 && read_page_no == 0) { /* This is likely an uninitialized page. */ - } else if ((bpage->id.space() != TRX_SYS_SPACE + } else if (((!space->full_crc32() + || bpage->id.space() != TRX_SYS_SPACE) && bpage->id.space() != read_space_id) || bpage->id.page_no() != read_page_no) { - /* We did not compare space_id to read_space_id - in the system tablespace, because the field - was written as garbage before MySQL 4.1.1, - which did not support innodb_file_per_table. */ + /* We do not compare space_id to read_space_id + in the system tablespace unless space->full_crc32(), + because the field was written as garbage before + MySQL 4.1.1, which introduced support for + innodb_file_per_table. */ + + if (space->full_crc32() + && *reinterpret_cast<uint32_t*> + (&frame[FIL_PAGE_FCRC32_KEY_VERSION]) + && space->crypt_data + && space->crypt_data->type + != CRYPT_SCHEME_UNENCRYPTED) { + ib::error() << "Cannot decrypt " << bpage->id; + err = DB_DECRYPTION_FAILED; + goto release_page; + } ib::error() << "Space id and page no stored in " "the page, read in are " @@ -6165,6 +6177,7 @@ database_corrupted: if (err == DB_PAGE_CORRUPTED || err == DB_DECRYPTION_FAILED) { +release_page: const page_id_t corrupt_page_id = bpage->id; buf_corrupt_page_release(bpage, space); |