diff --git a/mysql-test/r/percona_dd_upgrade_undo_encrypted.result b/mysql-test/r/percona_dd_upgrade_undo_encrypted.result new file mode 100644 index 000000000000..48c39da99fb1 --- /dev/null +++ b/mysql-test/r/percona_dd_upgrade_undo_encrypted.result @@ -0,0 +1,65 @@ +# Set different paths for --datadir +# Set path for undo* files. +# Set path for ibdata* files. +# Stop DB server which was created by MTR default, empty undo logs +SET GLOBAL innodb_fast_shutdown=0; +# Start the 8.0 server on 5.7 datadir with correct keyring_file +# Execute mysql_upgrade +mysql.columns_priv OK +mysql.component OK +mysql.db OK +mysql.default_roles OK +mysql.engine_cost OK +mysql.func OK +mysql.general_log OK +mysql.global_grants OK +mysql.gtid_executed OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.innodb_index_stats OK +mysql.innodb_table_stats OK +mysql.ndb_binlog_index OK +mysql.password_history OK +mysql.plugin OK +mysql.procs_priv OK +mysql.proxies_priv OK +mysql.role_edges OK +mysql.server_cost OK +mysql.servers OK +mysql.slave_master_info OK +mysql.slave_relay_log_info OK +mysql.slave_worker_info OK +mysql.slow_log OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK +sys.sys_config OK +test.tab1 OK +SHOW CREATE TABLE test.tab1; +Table Create Table +tab1 CREATE TABLE `tab1` ( + `c1` int(11) DEFAULT NULL, + `c2` varchar(30) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT * FROM tab1; +c1 c2 +100 aaaaa +200 bbbbb +300 aaaaa +400 bbbbb +# Now let's test what happens when encryption key is missing and we try to start 8.0 server on 5.7 directory +# with encrypted undo tablespaces +# Recreate the directories +# Check for errors in error log +# Corrupt undo encryption keys +# Now we check how the server behaves when undo encryption keys are corrupted +# Check for errors in error log +# Cleanup +# Restart the server with default options. +# restart diff --git a/mysql-test/std_data/undo57_encrypted.zip b/mysql-test/std_data/undo57_encrypted.zip new file mode 100644 index 000000000000..750d90097bda Binary files /dev/null and b/mysql-test/std_data/undo57_encrypted.zip differ diff --git a/mysql-test/t/percona_dd_upgrade_undo_encrypted-master.opt b/mysql-test/t/percona_dd_upgrade_undo_encrypted-master.opt new file mode 100644 index 000000000000..6758a595cae7 --- /dev/null +++ b/mysql-test/t/percona_dd_upgrade_undo_encrypted-master.opt @@ -0,0 +1 @@ +--bootstrap --innodb_page_size=16k diff --git a/mysql-test/t/percona_dd_upgrade_undo_encrypted.test b/mysql-test/t/percona_dd_upgrade_undo_encrypted.test new file mode 100644 index 000000000000..8ccb136ff957 --- /dev/null +++ b/mysql-test/t/percona_dd_upgrade_undo_encrypted.test @@ -0,0 +1,146 @@ +# This test contains keyring file created on 64bit which is not +# portable +--source include/have_64bit.inc +--source include/no_valgrind_without_big.inc +--source include/have_util_unzip.inc + +--disable_query_log +call mtr.add_suppression("Resizing redo log from"); +call mtr.add_suppression("Upgrading redo log"); +call mtr.add_suppression("Starting to delete and rewrite log files"); +call mtr.add_suppression("New log files created"); +call mtr.add_suppression("Unknown system variable 'show_compatibility_56'"); +call mtr.add_suppression("You need to use --log-bin to make --binlog-format work"); +call mtr.add_suppression("Creating routine without parsing routine body"); +call mtr.add_suppression("Resolving dependency for the view"); +call mtr.add_suppression("references invalid"); +call mtr.add_suppression("doesn't exist"); +call mtr.add_suppression("information_schema"); +call mtr.add_suppression("Storage engine '.*' does not support system tables. \\[mysql.*\\]"); +call mtr.add_suppression("Table 'mysql.component' doesn't exist"); +call mtr.add_suppression("is expected to be transactional"); +call mtr.add_suppression("table is missing or has an incorrect definition"); +call mtr.add_suppression("ACL DDLs will not work unless mysql_upgrade is executed"); +call mtr.add_suppression("Native table .* has the wrong structure"); +call mtr.add_suppression("Column count of mysql.* is wrong"); +call mtr.add_suppression("Cannot open table mysql/version from the internal data dictionary of InnoDB though the .frm file for the table exists"); +call mtr.add_suppression("Column count of performance_schema.events_statements_summary_by_digest is wrong"); +call mtr.add_suppression("The privilege system failed to initialize correctly"); +call mtr.add_suppression("Missing system table mysql.global_grants"); +# InnoDB reports "Lock wait timeout" warnings when it tries to drop persistent +# statistics while persistent statistics table is altered during upgrade. +# This issue doesn't seem to cause any further trouble (as there is no persistent +# stats for persistent stats table anyway), so we ignore these warnings here. +call mtr.add_suppression("Unable to delete statistics for table mysql."); +# new fields were added to these tables +call mtr.add_suppression("Column count of performance_schema.replication_group_members is wrong. Expected 7, found 5"); +call mtr.add_suppression("Column count of performance_schema.replication_group_member_stats is wrong. Expected 13, found 9"); +call mtr.add_suppression("Column count of performance_schema.threads is wrong. Expected 18, found 17"); +call mtr.add_suppression("ACL table mysql.[a-zA-Z_]* missing. Some operations may fail."); +call mtr.add_suppression("Info table is not ready to be used. Table 'mysql.slave_master_info' cannot be opened"); +call mtr.add_suppression("Error in checking mysql.slave_master_info repository info type of TABLE"); +call mtr.add_suppression("Error creating master info: Error checking repositories."); +call mtr.add_suppression("Slave: Failed to initialize the master info structure for channel"); +call mtr.add_suppression("Failed to create or recover replication info repositories."); +call mtr.add_suppression("db.opt file not found for test database. Using default Character set"); +call mtr.add_suppression("Skip re-populating collations and character sets tables in InnoDB read-only mode"); +call mtr.add_suppression("Skipped updating resource group metadata in InnoDB read only mode"); +--enable_query_log + +--echo # Set different paths for --datadir +let $MYSQLD_DATADIR1 = $MYSQL_TMP_DIR/undo57_encrypted/datadir/data; + +--echo # Set path for undo* files. +let $MYSQLD_UNDO_DATADIR = $MYSQL_TMP_DIR/undo57_encrypted/innodb_undo_data_dir; + +--echo # Set path for ibdata* files. +let $MYSQLD_HOME_DATA_DIR = $MYSQL_TMP_DIR/undo57_encrypted/innodb_data_home_dir; + +--copy_file $MYSQLTEST_VARDIR/std_data/undo57_encrypted.zip $MYSQL_TMP_DIR/undo57_encrypted.zip + +--exec unzip -qo $MYSQL_TMP_DIR/undo57_encrypted.zip -d $MYSQL_TMP_DIR + +--echo # Stop DB server which was created by MTR default, empty undo logs +SET GLOBAL innodb_fast_shutdown=0; +--source include/shutdown_mysqld.inc + +--echo # Start the 8.0 server on 5.7 datadir with correct keyring_file +--let $restart_parameters="restart: --early-plugin-load="keyring_file=$KEYRING_PLUGIN" $KEYRING_PLUGIN_OPT --keyring_file_data=$MYSQL_TMP_DIR/undo57_encrypted/my_key_undo5 --innodb_data_home_dir=$MYSQLD_HOME_DATA_DIR --innodb_undo_directory=$MYSQLD_UNDO_DATADIR --datadir=$MYSQLD_DATADIR1" +--replace_result $MYSQL_TMP_DIR TMP_DIR $KEYRING_PLUGIN_OPT --plugin-dir=KEYRING_PLUGIN_PATH $MYSQLD_HOME_DATA_DIR HOME_DIR $MYSQLD_UNDO_DATADIR UNDO_DATADIR $MYSQLD_DATADIR1 DATADIR +--source include/start_mysqld_no_echo.inc + +--echo # Execute mysql_upgrade + +--source include/mysql_upgrade_preparation.inc +--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 +--source include/mysql_upgrade_cleanup.inc + + +SHOW CREATE TABLE test.tab1; +SELECT * FROM tab1; + +--source include/shutdown_mysqld.inc + +--echo # Now let's test what happens when encryption key is missing and we try to start 8.0 server on 5.7 directory +--echo # with encrypted undo tablespaces +--echo # Recreate the directories +--force-rmdir $MYSQL_TMP_DIR/undo57_encrypted + +--exec unzip -qo $MYSQL_TMP_DIR/undo57_encrypted.zip -d $MYSQL_TMP_DIR + +--let $error_log=$MYSQLTEST_VARDIR/tmp/my_restart.err + +--error 1 +--exec $MYSQLD_CMD --log-error=$error_log --early-plugin-load="keyring_file=$KEYRING_PLUGIN" $KEYRING_PLUGIN_OPT --keyring_file_data=$MYSQL_TMP_DIR/my_empty_keyring --innodb_data_home_dir=$MYSQLD_HOME_DATA_DIR --innodb_undo_directory=$MYSQLD_UNDO_DATADIR --datadir=$MYSQLD_DATADIR1 + +--echo # Check for errors in error log + +--let ABORT_ON=NOT_FOUND +--let SEARCH_FILE=$error_log +--let SEARCH_PATTERN=Encryption can't find master key, please check the keyring plugin is loaded. +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Error reading encryption for innodb_undo001 +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= Unable to open undo tablespace number 1 +--source include/search_pattern_in_file.inc + +--echo # Corrupt undo encryption keys + +perl; +open(FILE, "+<", "$ENV{MYSQL_TMP_DIR}/undo57_encrypted/my_key_undo5") or die "open"; +binmode FILE; +seek(FILE, 77, SEEK_SET) or die "seek"; +print FILE pack("H*", "c00l"); +seek(FILE, 206, SEEK_SET) or die "seek"; +print FILE pack("H*", "c00l"); +close FILE or die "close"; +EOF + +--echo # Now we check how the server behaves when undo encryption keys are corrupted + +--let $error_log2=$MYSQLTEST_VARDIR/tmp/my_restart2.err + +--error 1 +--exec $MYSQLD_CMD --log-error=$error_log2 --early-plugin-load="keyring_file=$KEYRING_PLUGIN" $KEYRING_PLUGIN_OPT --keyring_file_data=$MYSQL_TMP_DIR/undo57_encrypted/my_key_undo5 --innodb_data_home_dir=$MYSQLD_HOME_DATA_DIR --innodb_undo_directory=$MYSQLD_UNDO_DATADIR --datadir=$MYSQLD_DATADIR1 + +--echo # Check for errors in error log + +--let ABORT_ON=NOT_FOUND +--let SEARCH_FILE=$error_log2 +--let SEARCH_PATTERN=Encryption can't find master key, please check the keyring plugin is loaded. +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Error reading encryption for innodb_undo001 +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= Unable to open undo tablespace number 1 +--source include/search_pattern_in_file.inc + +--echo # Cleanup +--remove_file $error_log +--remove_file $error_log2 +--remove_file $MYSQL_TMP_DIR/my_empty_keyring +--remove_file $MYSQL_TMP_DIR/undo57_encrypted.zip +--force-rmdir $MYSQL_TMP_DIR/undo57_encrypted + +--echo # Restart the server with default options. +--let $restart_parameters= +--source include/start_mysqld.inc diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a8a5614a27e6..63ceba5b8950 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -688,6 +688,9 @@ static dberr_t srv_undo_tablespace_read_encryption(pfs_os_file_t fh, /* Return if the encryption metadata is empty. */ if (memcmp(first_page + offset, ENCRYPTION_KEY_MAGIC_V3, + ENCRYPTION_MAGIC_SIZE) != 0 && + /* PS 5.7 undo encryption */ + memcmp(first_page + offset, ENCRYPTION_KEY_MAGIC_V2, ENCRYPTION_MAGIC_SIZE) != 0) { ut_free(first_page_buf); return (DB_SUCCESS);