mirror of
https://github.com/MariaDB/server.git
synced 2026-05-09 16:44:29 +02:00
MDEV-26747 improve corruption check for encrypted tables on ALTER IMPORT
fil_space_decrypt(): change signature to return status via dberr_t only. Also replace impossible condition with an assertion and prove it via test cases.
This commit is contained in:
parent
8f24f5fee2
commit
ed0a224b3d
7 changed files with 90 additions and 45 deletions
|
|
@ -0,0 +1,13 @@
|
|||
call mtr.add_suppression("InnoDB: .*: Page 0 at offset 0 looks corrupted");
|
||||
call mtr.add_suppression("Index for table 'dst' is corrupt; try to repair it");
|
||||
call mtr.add_suppression("Page for tablespace .* is index page with id .* but that index is not found from configuration file");
|
||||
CREATE TABLE src (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
|
||||
INSERT INTO src VALUES (1, 1), (2, 2), (3, 3);
|
||||
FLUSH TABLES src FOR EXPORT;
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE src;
|
||||
CREATE TABLE dst (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
|
||||
ALTER TABLE dst DISCARD TABLESPACE;
|
||||
ALTER TABLE dst IMPORT TABLESPACE;
|
||||
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`dst` : Data structure corruption
|
||||
DROP TABLE dst;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[crc32]
|
||||
innodb-checksum-algorithm=crc32
|
||||
[none]
|
||||
innodb-checksum-algorithm=none
|
||||
[innodb]
|
||||
innodb-checksum-algorithm=innodb
|
||||
|
|
@ -0,0 +1 @@
|
|||
--innodb-encrypt-tables=1
|
||||
44
mysql-test/suite/encryption/t/encryption_key_corruption.test
Normal file
44
mysql-test/suite/encryption/t/encryption_key_corruption.test
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/have_example_key_management_plugin.inc
|
||||
|
||||
call mtr.add_suppression("InnoDB: .*: Page 0 at offset 0 looks corrupted");
|
||||
call mtr.add_suppression("Index for table 'dst' is corrupt; try to repair it");
|
||||
call mtr.add_suppression("Page for tablespace .* is index page with id .* but that index is not found from configuration file");
|
||||
|
||||
let MYSQLD_DATADIR = `SELECT @@datadir`;
|
||||
|
||||
|
||||
CREATE TABLE src (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
|
||||
INSERT INTO src VALUES (1, 1), (2, 2), (3, 3);
|
||||
|
||||
FLUSH TABLES src FOR EXPORT;
|
||||
|
||||
--copy_file $MYSQLD_DATADIR/test/src.ibd $MYSQLD_DATADIR/test/tmp.ibd
|
||||
--copy_file $MYSQLD_DATADIR/test/src.cfg $MYSQLD_DATADIR/test/tmp.cfg
|
||||
|
||||
perl;
|
||||
use strict;
|
||||
die unless open(FILE, "+<$ENV{MYSQLD_DATADIR}/test/tmp.ibd");
|
||||
binmode FILE;
|
||||
die unless seek(FILE, 3 * 16384 + 26, 0);
|
||||
print FILE pack("N", 0x00000000);
|
||||
close(FILE);
|
||||
EOF
|
||||
|
||||
UNLOCK TABLES;
|
||||
|
||||
DROP TABLE src;
|
||||
|
||||
CREATE TABLE dst (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
|
||||
ALTER TABLE dst DISCARD TABLESPACE;
|
||||
|
||||
--copy_file $MYSQLD_DATADIR/test/tmp.ibd $MYSQLD_DATADIR/test/dst.ibd
|
||||
--copy_file $MYSQLD_DATADIR/test/tmp.cfg $MYSQLD_DATADIR/test/dst.cfg
|
||||
|
||||
--error ER_INTERNAL_ERROR
|
||||
ALTER TABLE dst IMPORT TABLESPACE;
|
||||
|
||||
DROP TABLE dst;
|
||||
|
||||
--remove_file $MYSQLD_DATADIR/test/tmp.ibd
|
||||
--remove_file $MYSQLD_DATADIR/test/tmp.cfg
|
||||
|
|
@ -668,16 +668,14 @@ fil_space_encrypt(
|
|||
@param[in] tmp_frame Temporary buffer
|
||||
@param[in] page_size Page size
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
|
||||
@return true if page decrypted, false if not.*/
|
||||
@return DB_SUCCESS or error */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
dberr_t
|
||||
fil_space_decrypt(
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
const page_size_t& page_size,
|
||||
byte* src_frame,
|
||||
dberr_t* err)
|
||||
byte* src_frame)
|
||||
{
|
||||
ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
|
||||
uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
|
||||
|
|
@ -686,12 +684,7 @@ fil_space_decrypt(
|
|||
uint space = mach_read_from_4(src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
|
||||
ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
|
||||
|
||||
*err = DB_SUCCESS;
|
||||
|
||||
if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ut_a(key_version != ENCRYPTION_KEY_NOT_ENCRYPTED);
|
||||
ut_a(crypt_data != NULL && crypt_data->is_encrypted());
|
||||
|
||||
/* read space & lsn */
|
||||
|
|
@ -722,8 +715,7 @@ fil_space_decrypt(
|
|||
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
|
||||
|
||||
if (rc == -1) {
|
||||
*err = DB_DECRYPTION_FAILED;
|
||||
return false;
|
||||
return DB_DECRYPTION_FAILED;
|
||||
}
|
||||
|
||||
ib::fatal() << "Unable to decrypt data-block "
|
||||
|
|
@ -748,7 +740,7 @@ fil_space_decrypt(
|
|||
|
||||
srv_stats.pages_decrypted.inc();
|
||||
|
||||
return true; /* page was decrypted */
|
||||
return DB_SUCCESS; /* page was decrypted */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -765,27 +757,21 @@ fil_space_decrypt(
|
|||
byte* tmp_frame,
|
||||
byte* src_frame)
|
||||
{
|
||||
dberr_t err = DB_SUCCESS;
|
||||
byte* res = NULL;
|
||||
const page_size_t page_size(space->flags);
|
||||
|
||||
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
|
||||
ut_ad(space->n_pending_ios > 0);
|
||||
|
||||
bool encrypted = fil_space_decrypt(space->crypt_data, tmp_frame,
|
||||
page_size, src_frame, &err);
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
if (encrypted) {
|
||||
/* Copy the decrypted page back to page buffer, not
|
||||
really any other options. */
|
||||
memcpy(src_frame, tmp_frame, page_size.physical());
|
||||
}
|
||||
|
||||
res = src_frame;
|
||||
if (DB_SUCCESS != fil_space_decrypt(space->crypt_data, tmp_frame,
|
||||
page_size, src_frame)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
/* Copy the decrypted page back to page buffer, not
|
||||
really any other options. */
|
||||
memcpy(src_frame, tmp_frame, page_size.physical());
|
||||
|
||||
return src_frame;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
|||
|
|
@ -359,16 +359,14 @@ Decrypt a page.
|
|||
@param[in] tmp_frame Temporary buffer
|
||||
@param[in] page_size Page size
|
||||
@param[in,out] src_frame Page to decrypt
|
||||
@param[out] err DB_SUCCESS or error
|
||||
@return true if page decrypted, false if not.*/
|
||||
@return DB_SUCCESS or error */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
dberr_t
|
||||
fil_space_decrypt(
|
||||
fil_space_crypt_t* crypt_data,
|
||||
byte* tmp_frame,
|
||||
const page_size_t& page_size,
|
||||
byte* src_frame,
|
||||
dberr_t* err);
|
||||
byte* src_frame);
|
||||
|
||||
/******************************************************************
|
||||
Decrypt a page
|
||||
|
|
|
|||
|
|
@ -3502,9 +3502,12 @@ page_corrupted:
|
|||
if (!fil_space_verify_crypt_checksum(readptr, get_page_size()))
|
||||
goto page_corrupted;
|
||||
|
||||
if (!fil_space_decrypt(iter.crypt_data, readptr,
|
||||
get_page_size(), readptr, &err) ||
|
||||
err != DB_SUCCESS)
|
||||
if (ENCRYPTION_KEY_NOT_ENCRYPTED ==
|
||||
mach_read_from_4(readptr + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION))
|
||||
goto page_corrupted;
|
||||
|
||||
if ((err = fil_space_decrypt(iter.crypt_data, readptr,
|
||||
get_page_size(), readptr)))
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
|
|
@ -3647,7 +3650,6 @@ page_corrupted:
|
|||
} else if (!mach_read_from_4(
|
||||
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
|
||||
+ src)) {
|
||||
not_encrypted:
|
||||
if (block->page.id.page_no() == 0
|
||||
&& block->page.zip.data) {
|
||||
block->page.zip.data = src;
|
||||
|
|
@ -3666,18 +3668,13 @@ not_encrypted:
|
|||
goto page_corrupted;
|
||||
}
|
||||
|
||||
decrypted = fil_space_decrypt(
|
||||
if ((err = fil_space_decrypt(
|
||||
iter.crypt_data, dst,
|
||||
callback.get_page_size(), src, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
callback.get_page_size(), src))) {
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (!decrypted) {
|
||||
goto not_encrypted;
|
||||
}
|
||||
|
||||
decrypted = true;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue