mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-8173: InnoDB; Failing assertion: crypt_data->type == 1
Make sure that when we publish the crypt_data we access the memory cache of the tablespace crypt_data. Make sure that crypt_data is stored whenever it is really needed. All this is not yet enough in my opinion because: sql/encryption.cc has DBUG_ASSERT(scheme->type == 1) i.e. crypt_data->type == CRYPT_SCHEME_1 However, for InnoDB point of view we have global crypt_data for every tablespace. When we change variables on crypt_data we take mutex. However, when we use crypt_data for encryption/decryption we use pointer to this global structure and no mutex to protect against changes on crypt_data. Tablespace encryption starts in fil_crypt_start_encrypting_space from crypt_data that has crypt_data->type = CRYPT_SCHEME_UNENCRYPTED and later we write page 0 CRYPT_SCHEME_1 and finally whe publish that to memory cache.
This commit is contained in:
@ -3,3 +3,15 @@ CREATE TABLE t1 (pk INT PRIMARY KEY, c VARCHAR(256));
|
||||
CREATE TABLE t2 AS SELECT * FROM t1;
|
||||
drop table t1,t2;
|
||||
SET GLOBAL innodb_encryption_threads = 0;
|
||||
SET GLOBAL innodb_encryption_threads = 4;
|
||||
CREATE TABLE `table10_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int, key (`col_int_key` ),primary key (pk)) engine=innodb;
|
||||
INSERT /*! IGNORE */ INTO table10_int_autoinc VALUES (NULL, NULL, -474021888) , (1, NULL, NULL) , (1141047296, NULL, NULL) , (NULL, NULL, NULL) , (NULL, NULL, 1) , (NULL, NULL, 9) , (0, NULL, 1225785344) , (NULL, NULL, 1574174720) , (2, NULL, NULL) , (6, NULL, 3);
|
||||
CREATE TABLE `table1_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int,key (`col_int_key` ), primary key (pk)) engine=innodb;
|
||||
CREATE TABLE `table0_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int, key (`col_int_key` ),primary key (pk)) engine=innodb;
|
||||
INSERT /*! IGNORE */ INTO table1_int_autoinc VALUES (4, NULL, NULL);
|
||||
INSERT IGNORE INTO `table0_int_autoinc` ( `col_int_key` ) VALUES ( 1 ), ( 3 ), ( 4 ), ( 1 );
|
||||
INSERT IGNORE INTO `table1_int_autoinc` ( `col_int` ) VALUES ( 1 ), ( 0 ), ( 7 ), ( 9 );
|
||||
INSERT IGNORE INTO `table10_int_autoinc` ( `col_int` ) VALUES ( 6 ), ( 2 ), ( 3 ), ( 6 );
|
||||
drop table if exists create_or_replace_t, table1_int_autoinc, table0_int_autoinc, table10_int_autoinc;
|
||||
SET GLOBAL innodb_encryption_threads = 0;
|
||||
SET GLOBAL innodb_encrypt_tables = OFF;
|
||||
|
@ -34,3 +34,76 @@ dec $i;
|
||||
|
||||
drop table t1,t2;
|
||||
SET GLOBAL innodb_encryption_threads = 0;
|
||||
|
||||
#
|
||||
# MDEV-8173: InnoDB; Failing assertion: crypt_data->type == 1
|
||||
#
|
||||
|
||||
SET GLOBAL innodb_encryption_threads = 4;
|
||||
|
||||
CREATE TABLE `table10_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int, key (`col_int_key` ),primary key (pk)) engine=innodb;
|
||||
INSERT /*! IGNORE */ INTO table10_int_autoinc VALUES (NULL, NULL, -474021888) , (1, NULL, NULL) , (1141047296, NULL, NULL) , (NULL, NULL, NULL) , (NULL, NULL, 1) , (NULL, NULL, 9) , (0, NULL, 1225785344) , (NULL, NULL, 1574174720) , (2, NULL, NULL) , (6, NULL, 3);
|
||||
|
||||
CREATE TABLE `table1_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int,key (`col_int_key` ), primary key (pk)) engine=innodb;
|
||||
|
||||
CREATE TABLE `table0_int_autoinc` (`col_int_key` int, pk int auto_increment, `col_int` int, key (`col_int_key` ),primary key (pk)) engine=innodb;
|
||||
|
||||
INSERT /*! IGNORE */ INTO table1_int_autoinc VALUES (4, NULL, NULL);
|
||||
INSERT IGNORE INTO `table0_int_autoinc` ( `col_int_key` ) VALUES ( 1 ), ( 3 ), ( 4 ), ( 1 );
|
||||
INSERT IGNORE INTO `table1_int_autoinc` ( `col_int` ) VALUES ( 1 ), ( 0 ), ( 7 ), ( 9 );
|
||||
INSERT IGNORE INTO `table10_int_autoinc` ( `col_int` ) VALUES ( 6 ), ( 2 ), ( 3 ), ( 6 );
|
||||
|
||||
--connect (con1,localhost,root,,test)
|
||||
--connect (con2,localhost,root,,test)
|
||||
|
||||
--disable_abort_on_error
|
||||
--disable_warnings
|
||||
--disable_query_log
|
||||
|
||||
let $i = 500;
|
||||
while ($i)
|
||||
{
|
||||
connection con1;
|
||||
send SET GLOBAL innodb_encrypt_tables = ON;
|
||||
connection default;
|
||||
CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table1_int_autoinc`;
|
||||
connection con2;
|
||||
send CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table10_int_autoinc`;
|
||||
connection default;
|
||||
send CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table0_int_autoinc`;
|
||||
connection con1;
|
||||
--reap;
|
||||
send SET GLOBAL innodb_encrypt_tables = OFF;
|
||||
connection con2;
|
||||
--reap;
|
||||
connection default;
|
||||
--reap;
|
||||
send CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table1_int_autoinc`;
|
||||
connection con2;
|
||||
send CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table10_int_autoinc`;
|
||||
connection con1;
|
||||
--reap;
|
||||
send SET GLOBAL innodb_encrypt_tables = ON;
|
||||
connection default;
|
||||
--reap;
|
||||
send CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table1_int_autoinc`;
|
||||
connection con2;
|
||||
--reap;
|
||||
CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table10_int_autoinc`;
|
||||
CREATE OR REPLACE TABLE `create_or_replace_t` AS SELECT * FROM `table0_int_autoinc`;
|
||||
connection con1;
|
||||
--reap;
|
||||
connection default;
|
||||
--reap;
|
||||
dec $i;
|
||||
}
|
||||
|
||||
--enable_query_log
|
||||
connection default;
|
||||
drop table if exists create_or_replace_t, table1_int_autoinc, table0_int_autoinc, table10_int_autoinc;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
--enable_abort_on_error
|
||||
--enable_warnings
|
||||
SET GLOBAL innodb_encryption_threads = 0;
|
||||
SET GLOBAL innodb_encrypt_tables = OFF;
|
||||
|
@ -169,7 +169,13 @@ int do_crypt(const unsigned char* src, unsigned int slen,
|
||||
compile_time_assert(ENCRYPTION_SCHEME_KEY_INVALID ==
|
||||
(int)ENCRYPTION_KEY_VERSION_INVALID);
|
||||
|
||||
DBUG_ASSERT(scheme->type == 1);
|
||||
// Maybe temporal solution for MDEV-8173
|
||||
// Rationale: scheme->type is currently global/object
|
||||
// and when used here might not represent actual state
|
||||
// of smaller granularity objects e.g. InnoDB page state
|
||||
// as type is stored to tablespace (FIL) and could represent
|
||||
// state where key rotation is trying to reach
|
||||
//DBUG_ASSERT(scheme->type == 1);
|
||||
|
||||
if (key_version == ENCRYPTION_KEY_VERSION_INVALID ||
|
||||
key_version == ENCRYPTION_KEY_NOT_ENCRYPTED)
|
||||
|
@ -4334,7 +4334,7 @@ corrupt:
|
||||
"InnoDB: space %lu file %s read of page %lu.\n"
|
||||
"InnoDB: You may have to recover"
|
||||
" from a backup.\n",
|
||||
bpage->space,
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) bpage->offset);
|
||||
buf_page_print(frame, buf_page_get_zip_size(bpage),
|
||||
|
@ -266,13 +266,8 @@ fil_space_read_crypt_data(
|
||||
ulint offset) /*!< in: offset */
|
||||
{
|
||||
if (memcmp(page + offset, EMPTY_PATTERN, MAGIC_SZ) == 0) {
|
||||
/* crypt is not stored but create memory cache for
|
||||
not system tablespace */
|
||||
if (space != 0) {
|
||||
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
/* Crypt data is not stored. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
|
||||
@ -288,12 +283,8 @@ fil_space_read_crypt_data(
|
||||
page[offset + 3],
|
||||
page[offset + 4],
|
||||
page[offset + 5]);
|
||||
/* Create memory cache for not system tablespace */
|
||||
if (space != 0) {
|
||||
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
/* Create data is not stored. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulint type = mach_read_from_1(page + offset + MAGIC_SZ + 0);
|
||||
@ -461,12 +452,6 @@ fil_space_write_crypt_data(
|
||||
return;
|
||||
}
|
||||
|
||||
/* If tablespace encryption is disabled and encryption mode is
|
||||
DEFAULT, then do not continue writing crypt data to page 0. */
|
||||
if (!srv_encrypt_tables && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||
return;
|
||||
}
|
||||
|
||||
fil_space_write_crypt_data_low(crypt_data, crypt_data->type,
|
||||
page, offset, maxsize, mtr);
|
||||
}
|
||||
@ -1073,7 +1058,7 @@ fil_crypt_start_encrypting_space(
|
||||
crypt_data->rotate_state.active_threads = 1;
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
fil_space_set_crypt_data(space, crypt_data);
|
||||
crypt_data = fil_space_set_crypt_data(space, crypt_data);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
|
||||
fil_crypt_start_converting = true;
|
||||
@ -1108,6 +1093,7 @@ fil_crypt_start_encrypting_space(
|
||||
/* 3 - compute location to store crypt data */
|
||||
byte* frame = buf_block_get_frame(block);
|
||||
ulint maxsize;
|
||||
ut_ad(crypt_data);
|
||||
crypt_data->page0_offset =
|
||||
fsp_header_get_crypt_offset(zip_size, &maxsize);
|
||||
|
||||
@ -1160,6 +1146,7 @@ fil_crypt_start_encrypting_space(
|
||||
|
||||
/* 5 - publish crypt data */
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
crypt_data->type = CRYPT_SCHEME_1;
|
||||
ut_a(crypt_data->rotate_state.active_threads == 1);
|
||||
@ -1173,6 +1160,7 @@ fil_crypt_start_encrypting_space(
|
||||
return pending_op;
|
||||
} while (0);
|
||||
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
ut_a(crypt_data->rotate_state.active_threads == 1);
|
||||
crypt_data->rotate_state.active_threads = 0;
|
||||
|
@ -6855,7 +6855,7 @@ fil_space_get_crypt_data(
|
||||
/******************************************************************
|
||||
Get crypt data for a tablespace */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_crypt_t*
|
||||
fil_space_set_crypt_data(
|
||||
/*=====================*/
|
||||
ulint id, /*!< in: space id */
|
||||
@ -6863,6 +6863,7 @@ fil_space_set_crypt_data(
|
||||
{
|
||||
fil_space_t* space;
|
||||
fil_space_crypt_t* free_crypt_data = NULL;
|
||||
fil_space_crypt_t* ret_crypt_data = NULL;
|
||||
|
||||
ut_ad(fil_system);
|
||||
|
||||
@ -6881,9 +6882,11 @@ fil_space_set_crypt_data(
|
||||
mutex_exit(&fil_system->mutex);
|
||||
fil_space_merge_crypt_data(space->crypt_data,
|
||||
crypt_data);
|
||||
ret_crypt_data = space->crypt_data;
|
||||
free_crypt_data = crypt_data;
|
||||
} else {
|
||||
space->crypt_data = crypt_data;
|
||||
ret_crypt_data = space->crypt_data;
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
} else {
|
||||
@ -6899,4 +6902,6 @@ fil_space_set_crypt_data(
|
||||
*/
|
||||
fil_space_destroy_crypt_data(&free_crypt_data);
|
||||
}
|
||||
|
||||
return ret_crypt_data;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ fil_space_get_crypt_data(
|
||||
/*********************************************************************
|
||||
Set crypt data for a space*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_crypt_t*
|
||||
fil_space_set_crypt_data(
|
||||
/*=====================*/
|
||||
ulint space, /*!< in: tablespace id */
|
||||
|
@ -4414,7 +4414,7 @@ corrupt:
|
||||
"InnoDB: space %lu file %s read of page %lu.\n"
|
||||
"InnoDB: You may have to recover"
|
||||
" from a backup.\n",
|
||||
bpage->space,
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) bpage->offset);
|
||||
|
||||
|
@ -266,13 +266,8 @@ fil_space_read_crypt_data(
|
||||
ulint offset) /*!< in: offset */
|
||||
{
|
||||
if (memcmp(page + offset, EMPTY_PATTERN, MAGIC_SZ) == 0) {
|
||||
/* crypt is not stored but create memory cache for
|
||||
not system tablespace */
|
||||
if (space != 0) {
|
||||
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
/* Crypt data is not stored. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
|
||||
@ -288,12 +283,8 @@ fil_space_read_crypt_data(
|
||||
page[offset + 3],
|
||||
page[offset + 4],
|
||||
page[offset + 5]);
|
||||
/* Create memory cache for not system tablespace */
|
||||
if (space != 0) {
|
||||
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
/* Crypt data is not stored. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulint type = mach_read_from_1(page + offset + MAGIC_SZ + 0);
|
||||
@ -461,12 +452,6 @@ fil_space_write_crypt_data(
|
||||
return;
|
||||
}
|
||||
|
||||
/* If tablespace encryption is disabled and encryption mode is
|
||||
DEFAULT, then do not continue writing crypt data to page 0. */
|
||||
if (!srv_encrypt_tables && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||
return;
|
||||
}
|
||||
|
||||
fil_space_write_crypt_data_low(crypt_data, crypt_data->type,
|
||||
page, offset, maxsize, mtr);
|
||||
}
|
||||
@ -1073,7 +1058,7 @@ fil_crypt_start_encrypting_space(
|
||||
crypt_data->rotate_state.active_threads = 1;
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
fil_space_set_crypt_data(space, crypt_data);
|
||||
crypt_data = fil_space_set_crypt_data(space, crypt_data);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
|
||||
fil_crypt_start_converting = true;
|
||||
@ -1108,6 +1093,7 @@ fil_crypt_start_encrypting_space(
|
||||
/* 3 - compute location to store crypt data */
|
||||
byte* frame = buf_block_get_frame(block);
|
||||
ulint maxsize;
|
||||
ut_ad(crypt_data);
|
||||
crypt_data->page0_offset =
|
||||
fsp_header_get_crypt_offset(zip_size, &maxsize);
|
||||
|
||||
@ -1160,6 +1146,7 @@ fil_crypt_start_encrypting_space(
|
||||
|
||||
/* 5 - publish crypt data */
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
crypt_data->type = CRYPT_SCHEME_1;
|
||||
ut_a(crypt_data->rotate_state.active_threads == 1);
|
||||
@ -1173,6 +1160,7 @@ fil_crypt_start_encrypting_space(
|
||||
return pending_op;
|
||||
} while (0);
|
||||
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
ut_a(crypt_data->rotate_state.active_threads == 1);
|
||||
crypt_data->rotate_state.active_threads = 0;
|
||||
|
@ -6982,7 +6982,7 @@ fil_space_get_crypt_data(
|
||||
/******************************************************************
|
||||
Get crypt data for a tablespace */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_crypt_t*
|
||||
fil_space_set_crypt_data(
|
||||
/*==================*/
|
||||
ulint id, /*!< in: space id */
|
||||
@ -6990,6 +6990,7 @@ fil_space_set_crypt_data(
|
||||
{
|
||||
fil_space_t* space;
|
||||
fil_space_crypt_t* free_crypt_data = NULL;
|
||||
fil_space_crypt_t* ret_crypt_data = NULL;
|
||||
|
||||
ut_ad(fil_system);
|
||||
|
||||
@ -7008,9 +7009,11 @@ fil_space_set_crypt_data(
|
||||
mutex_exit(&fil_system->mutex);
|
||||
fil_space_merge_crypt_data(space->crypt_data,
|
||||
crypt_data);
|
||||
ret_crypt_data = space->crypt_data;
|
||||
free_crypt_data = crypt_data;
|
||||
} else {
|
||||
space->crypt_data = crypt_data;
|
||||
ret_crypt_data = space->crypt_data;
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
} else {
|
||||
@ -7026,4 +7029,6 @@ fil_space_set_crypt_data(
|
||||
*/
|
||||
fil_space_destroy_crypt_data(&free_crypt_data);
|
||||
}
|
||||
|
||||
return ret_crypt_data;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ fil_space_get_crypt_data(
|
||||
/*********************************************************************
|
||||
Set crypt data for a space*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_crypt_t*
|
||||
fil_space_set_crypt_data(
|
||||
/*=====================*/
|
||||
ulint space, /*!< in: tablespace id */
|
||||
|
Reference in New Issue
Block a user