diff options
-rw-r--r-- | mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result | 19 | ||||
-rw-r--r-- | mysql-test/suite/encryption/r/innodb-log-encrypt.result | 36 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt | 6 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test | 38 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-log-encrypt.test | 20 | ||||
-rw-r--r-- | storage/innobase/include/log0recv.h | 12 | ||||
-rw-r--r-- | storage/innobase/log/log0crypt.cc | 13 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 21 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 20 | ||||
-rw-r--r-- | storage/xtradb/include/log0recv.h | 3 | ||||
-rw-r--r-- | storage/xtradb/log/log0crypt.cc | 41 | ||||
-rw-r--r-- | storage/xtradb/log/log0log.cc | 36 | ||||
-rw-r--r-- | storage/xtradb/log/log0online.cc | 2 | ||||
-rw-r--r-- | storage/xtradb/log/log0recv.cc | 37 |
14 files changed, 237 insertions, 67 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result b/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result new file mode 100644 index 00000000000..5310fb6ace2 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result @@ -0,0 +1,19 @@ +call mtr.add_suppression("InnoDB: New log files created, LSN=.*"); +call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables."); +call mtr.add_suppression("InnoDB: Error: Table .*"); +CREATE TABLE t1 ( +pk bigint auto_increment, +col_int int, +col_int_key int, +col_char char(12), +col_char_key char(12), +primary key (pk), +key (`col_int_key` ), +key (`col_char_key` ) +) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (NULL,1,1,'foo','foo'),(NULL,2,2,'bar','bar'),(NULL,3,3,'baz','baz'),(NULL,4,4,'qux','qux'); +INSERT INTO t2 +SELECT NULL, a1.col_int, a1.col_int_key, a1.col_char, a1.col_char_key +FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5, t1 a6, t1 a7, t1 a8, t1 a9, t1 a10; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/r/innodb-log-encrypt.result b/mysql-test/suite/encryption/r/innodb-log-encrypt.result index 3e281efd08a..655e3023f7a 100644 --- a/mysql-test/suite/encryption/r/innodb-log-encrypt.result +++ b/mysql-test/suite/encryption/r/innodb-log-encrypt.result @@ -8,7 +8,7 @@ begin declare current_num int; set current_num = 0; while current_num < repeat_count do -insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('secredsecredsecred',10)); +insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('privatejanprivate',10)); set current_num = current_num + 1; end while; end// @@ -22,34 +22,34 @@ select count(*) from t1; count(*) 2000 # ibdata1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ibdata1 +NOT FOUND /privatejanprivate/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in t1.ibd +NOT FOUND /privatejanprivate/ in t1.ibd # log0 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile0 +NOT FOUND /privatejanprivate/ in ib_logfile0 # log1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile1 +NOT FOUND /privatejanprivate/ in ib_logfile1 # Restart mysqld --innodb_encrypt_log=0 -insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); +insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); # ibdata1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ibdata1 +NOT FOUND /privatejanprivate/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in t1.ibd +NOT FOUND /privatejanprivate/ in t1.ibd # log0 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile0 +NOT FOUND /privatejanprivate/ in ib_logfile0 # log1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile1 +NOT FOUND /privatejanprivate/ in ib_logfile1 # ibdata1 yes on expecting NOT FOUND -NOT FOUND /notsecred/ in ibdata1 +NOT FOUND /publicmessage/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /notsecred/ in t1.ibd +NOT FOUND /publicmessage/ in t1.ibd # log0 no on expecting FOUND/NOTFOUND depending where insert goes -FOUND /notsecred/ in ib_logfile0 +FOUND /publicmessage/ in ib_logfile0 # log1 no on expecting FOUND/NOTFOUND depending where insert goes -NOT FOUND /notsecred/ in ib_logfile1 +NOT FOUND /publicmessage/ in ib_logfile1 drop procedure innodb_insert_proc; drop table t1; diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt new file mode 100644 index 00000000000..e76aa060879 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt @@ -0,0 +1,6 @@ +--innodb-encrypt-log=ON +--plugin-load-add=$FILE_KEY_MANAGEMENT_SO +--loose-file-key-management +--loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/logkey.txt +--file-key-management-encryption-algorithm=aes_cbc +--innodb-buffer-pool-size=128M diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test new file mode 100644 index 00000000000..8bb5f9f2c49 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test @@ -0,0 +1,38 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc +-- source filekeys_plugin.inc + +call mtr.add_suppression("InnoDB: New log files created, LSN=.*"); +call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables."); +call mtr.add_suppression("InnoDB: Error: Table .*"); + +# +# MDEV-9422: Checksum errors on restart when killing busy instance that uses encrypted XtraDB tables +# + +CREATE TABLE t1 ( + pk bigint auto_increment, + col_int int, + col_int_key int, + col_char char(12), + col_char_key char(12), + primary key (pk), + key (`col_int_key` ), + key (`col_char_key` ) +) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; + +INSERT INTO t1 VALUES (NULL,1,1,'foo','foo'),(NULL,2,2,'bar','bar'),(NULL,3,3,'baz','baz'),(NULL,4,4,'qux','qux'); +INSERT INTO t2 + SELECT NULL, a1.col_int, a1.col_int_key, a1.col_char, a1.col_char_key + FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5, t1 a6, t1 a7, t1 a8, t1 a9, t1 a10; + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server 0 +--source include/wait_until_disconnected.inc + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt.test b/mysql-test/suite/encryption/t/innodb-log-encrypt.test index b2abfadccc2..7c2e6f847b1 100644 --- a/mysql-test/suite/encryption/t/innodb-log-encrypt.test +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt.test @@ -28,7 +28,7 @@ begin declare current_num int; set current_num = 0; while current_num < repeat_count do - insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('secredsecredsecred',10)); + insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('privatejanprivate',10)); set current_num = current_num + 1; end while; end// @@ -43,13 +43,15 @@ set autocommit=1; update t1 set c1 = c1 +1; select count(*) from t1; +-- source include/restart_mysqld.inc + --let $MYSQLD_DATADIR=`select @@datadir` --let ib1_IBD = $MYSQLD_DATADIR/ibdata1 --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd --let log0 = $MYSQLD_DATADIR/ib_logfile0 --let log1 = $MYSQLD_DATADIR/ib_logfile1 --let SEARCH_RANGE = 10000000 ---let SEARCH_PATTERN=secredsecred +--let SEARCH_PATTERN=privatejanprivate --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD @@ -68,13 +70,13 @@ select count(*) from t1; -- let $restart_parameters=--innodb_encrypt_log=0 -- source include/restart_mysqld.inc -insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); +insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); ---let SEARCH_PATTERN=secredsecred +--let SEARCH_PATTERN=privatejanprivate --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD -- source include/search_pattern_in_file.inc @@ -88,7 +90,7 @@ insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)) -- let SEARCH_FILE=$log1 -- source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=notsecred +--let SEARCH_PATTERN=publicmessage --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD -- source include/search_pattern_in_file.inc diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index e4a06fcc532..292953854f7 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -498,6 +498,18 @@ use these free frames to read in pages when we start applying the log records to the database. */ extern ulint recv_n_pool_free_frames; +/******************************************************//** +Checks the 4-byte checksum to the trailer checksum field of a log +block. We also accept a log block in the old format before +InnoDB-3.23.52 where the checksum field contains the log block number. +@return TRUE if ok, or if the log block may be in the format of InnoDB +version predating 3.23.52 */ +ibool +log_block_checksum_is_ok_or_old_format( +/*===================================*/ + const byte* block, /*!< in: pointer to a log block */ + bool print_err); /*!< in print error ? */ + #ifndef UNIV_NONINL #include "log0recv.ic" #endif diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index e90533c2e76..00de0252d6e 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -156,12 +156,21 @@ log_blocks_crypt( info ? info->key_version : 0, log_block_start_lsn); #endif + /* If no key is found from checkpoint assume the log_block + to be unencrypted. If checkpoint contains the encryption key + compare log_block current checksum, if checksum matches, + block can't be encrypted. */ if (info == NULL || - info->key_version == UNENCRYPTED_KEY_VER) { + info->key_version == UNENCRYPTED_KEY_VER || + (log_block_checksum_is_ok_or_old_format(log_block, false) && + what == ENCRYPTION_FLAG_DECRYPT)) { memcpy(dst_block, log_block, OS_FILE_LOG_BLOCK_SIZE); goto next; } + ut_ad(what == ENCRYPTION_FLAG_DECRYPT ? !log_block_checksum_is_ok_or_old_format(log_block, false) : + log_block_checksum_is_ok_or_old_format(log_block, false)); + // Assume log block header is not encrypted memcpy(dst_block, log_block, LOG_BLOCK_HDR_SIZE); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index fd3646a1691..31104b395c1 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2013, SkySQL Ab. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -52,6 +52,9 @@ Created 12/9/1995 Heikki Tuuri #include "trx0roll.h" #include "srv0mon.h" +/* Used for debugging */ +// #define DEBUG_CRYPT 1 + /* General philosophy of InnoDB redo-logs: @@ -2358,8 +2361,24 @@ loop: (ulint) (source_offset % UNIV_PAGE_SIZE), len, buf, NULL, 0); +#ifdef DEBUG_CRYPT + fprintf(stderr, "BEFORE DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx offset %lu\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf), source_offset); +#endif + log_decrypt_after_read(buf, len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "AFTER DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + start_lsn += len; buf += len; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index c84e8277f07..6e09143fb96 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -923,11 +923,11 @@ block. We also accept a log block in the old format before InnoDB-3.23.52 where the checksum field contains the log block number. @return TRUE if ok, or if the log block may be in the format of InnoDB version predating 3.23.52 */ -static ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block) /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err) /*!< in print error ? */ { #ifdef UNIV_LOG_DEBUG return(TRUE); @@ -950,11 +950,13 @@ log_block_checksum_is_ok_or_old_format( return(TRUE); } - fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", - log_block_get_hdr_no(block), - log_block_get_checkpoint_no(block), - log_block_calc_checksum(block), - log_block_get_checksum(block)); + if (print_err) { + fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(block), + log_block_get_checkpoint_no(block), + log_block_calc_checksum(block), + log_block_get_checksum(block)); + } return(FALSE); } @@ -2686,12 +2688,12 @@ recv_scan_log_recs( log_block_convert_lsn_to_no(scanned_lsn)); */ if (no != log_block_convert_lsn_to_no(scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { + || !log_block_checksum_is_ok_or_old_format(log_block, true)) { log_crypt_err_t log_crypt_err; if (no == log_block_convert_lsn_to_no(scanned_lsn) && !log_block_checksum_is_ok_or_old_format( - log_block)) { + log_block, true)) { fprintf(stderr, "InnoDB: Log block no %lu at" " lsn " LSN_PF " has\n" diff --git a/storage/xtradb/include/log0recv.h b/storage/xtradb/include/log0recv.h index b23a140aac2..8fc5daaef1d 100644 --- a/storage/xtradb/include/log0recv.h +++ b/storage/xtradb/include/log0recv.h @@ -43,7 +43,8 @@ UNIV_INTERN ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block); /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err); /*!< in print error ? */ /*******************************************************//** Calculates the new value for lsn when more data is added to the log. */ diff --git a/storage/xtradb/log/log0crypt.cc b/storage/xtradb/log/log0crypt.cc index e90533c2e76..852148899e9 100644 --- a/storage/xtradb/log/log0crypt.cc +++ b/storage/xtradb/log/log0crypt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,6 +36,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com #include "my_crypt.h" +/* Used for debugging */ +// #define DEBUG_CRYPT 1 #define UNENCRYPTED_KEY_VER 0 /* If true, enable redo log encryption. */ @@ -97,16 +99,24 @@ get_crypt_info( { /* so that no one is modifying array while we search */ ut_ad(mutex_own(&(log_sys->mutex))); + size_t items = crypt_info.size(); /* a log block only stores 4-bytes of checkpoint no */ checkpoint_no &= 0xFFFFFFFF; - for (size_t i = 0; i < crypt_info.size(); i++) { + for (size_t i = 0; i < items; i++) { struct crypt_info_t* it = &crypt_info[i]; if (it->checkpoint_no == checkpoint_no) { return it; } } + + /* If checkpoint contains more than one key and we did not + find the correct one use the first one. */ + if (items) { + return (&crypt_info[0]); + } + return NULL; } @@ -131,7 +141,8 @@ log_blocks_crypt( const byte* block, /*!< in: blocks before encrypt/decrypt*/ ulint size, /*!< in: size of block */ byte* dst_block, /*!< out: blocks after encrypt/decrypt */ - int what) /*!< in: encrypt or decrypt*/ + int what, /*!< in: encrypt or decrypt*/ + const crypt_info_t* crypt_info) /*!< in: crypt info or NULL */ { byte *log_block = (byte*)block; Crypt_result rc = MY_AES_OK; @@ -146,7 +157,8 @@ log_blocks_crypt( lsn_t log_block_start_lsn = log_block_get_start_lsn( lsn, log_block_no); - const crypt_info_t* info = get_crypt_info(log_block); + const crypt_info_t* info = crypt_info == NULL ? get_crypt_info(log_block) : + crypt_info; #ifdef DEBUG_CRYPT fprintf(stderr, "%s %lu chkpt: %lu key: %u lsn: %lu\n", @@ -156,12 +168,21 @@ log_blocks_crypt( info ? info->key_version : 0, log_block_start_lsn); #endif + /* If no key is found from checkpoint assume the log_block + to be unencrypted. If checkpoint contains the encryption key + compare log_block current checksum, if checksum matches, + block can't be encrypted. */ if (info == NULL || - info->key_version == UNENCRYPTED_KEY_VER) { + info->key_version == UNENCRYPTED_KEY_VER || + (log_block_checksum_is_ok_or_old_format(log_block, false) && + what == ENCRYPTION_FLAG_DECRYPT)) { memcpy(dst_block, log_block, OS_FILE_LOG_BLOCK_SIZE); goto next; } + ut_ad(what == ENCRYPTION_FLAG_DECRYPT ? !log_block_checksum_is_ok_or_old_format(log_block, false) : + log_block_checksum_is_ok_or_old_format(log_block, false)); + // Assume log block header is not encrypted memcpy(dst_block, log_block, LOG_BLOCK_HDR_SIZE); @@ -292,7 +313,7 @@ log_blocks_encrypt( const ulint size, /*!< in: size of blocks, must be multiple of a log block */ byte* dst_block) /*!< out: blocks after encryption */ { - return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT); + return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT, NULL); } /*********************************************************************//** @@ -355,14 +376,16 @@ log_encrypt_before_write( return; } - if (info->key_version == UNENCRYPTED_KEY_VER) { + /* If the key is not encrypted or user has requested not to + encrypt, do not change log block. */ + if (info->key_version == UNENCRYPTED_KEY_VER || !srv_encrypt_log) { return; } byte* dst_frame = (byte*)malloc(size); //encrypt log blocks content - Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT); + Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT, NULL); if (result == MY_AES_OK) { ut_ad(block[0] == dst_frame[0]); @@ -388,7 +411,7 @@ log_decrypt_after_read( byte* dst_frame = (byte*)malloc(size); // decrypt log blocks content - Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT); + Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT, NULL); if (result == MY_AES_OK) { memcpy(frame, dst_frame, size); diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index 853afe70100..36531f3c6f4 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -33,10 +34,13 @@ Created 12/9/1995 Heikki Tuuri #include "config.h" #ifdef HAVE_ALLOCA_H #include "alloca.h" -#elif defined(HAVE_MALLOC_H) +#elif defined(HAVE_MALLOC_H) #include "malloc.h" #endif +/* Used for debugging */ +// #define DEBUG_CRYPT 1 + #include "log0log.h" #ifdef UNIV_NONINL @@ -1394,7 +1398,6 @@ log_group_file_header_flush( Stores a 4-byte checksum to the trailer checksum field of a log block before writing it to a log file. This checksum is used in recovery to check the consistency of a log block. */ -static void log_block_store_checksum( /*=====================*/ @@ -1512,6 +1515,14 @@ loop: log_encrypt_before_write(log_sys->next_checkpoint_no, buf, write_len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "WRITE: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + fil_io(OS_FILE_WRITE | OS_FILE_LOG, true, group->space_id, 0, (ulint) (next_offset / UNIV_PAGE_SIZE), (ulint) (next_offset % UNIV_PAGE_SIZE), write_len, buf, @@ -2320,7 +2331,10 @@ log_checkpoint( * the checkpoint info has been written and THEN blocks will be encrypted * with new key */ - log_crypt_set_ver_and_key(log_sys->next_checkpoint_no + 1); + if (srv_encrypt_log) { + log_crypt_set_ver_and_key(log_sys->next_checkpoint_no + 1); + } + log_groups_write_checkpoint_info(); MONITOR_INC(MONITOR_NUM_CHECKPOINT); @@ -2585,8 +2599,24 @@ loop: mutex_enter(&log_sys->mutex); } +#ifdef DEBUG_CRYPT + fprintf(stderr, "BEFORE DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx offset %lu\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf), source_offset); +#endif + log_decrypt_after_read(buf, len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "AFTER DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + if (release_mutex) { mutex_exit(&log_sys->mutex); } diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 92f03f0e6a9..51a9fa8f6c5 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -905,7 +905,7 @@ log_online_is_valid_log_seg( const byte* log_block) /*!< in: read log data */ { ibool checksum_is_ok - = log_block_checksum_is_ok_or_old_format(log_block); + = log_block_checksum_is_ok_or_old_format(log_block, true); if (!checksum_is_ok) { diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index c9bf5cf3f9e..f98adbbca08 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/log/log0recv.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -43,7 +43,7 @@ Created 9/20/1997 Heikki Tuuri #include "config.h" #ifdef HAVE_ALLOCA_H #include "alloca.h" -#elif defined(HAVE_MALLOC_H) +#elif defined(HAVE_MALLOC_H) #include "malloc.h" #endif @@ -932,7 +932,8 @@ UNIV_INTERN ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block) /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err) /*!< in print if error found */ { #ifdef UNIV_LOG_DEBUG return(TRUE); @@ -1015,11 +1016,13 @@ log_block_checksum_is_ok_or_old_format( return(TRUE); } - fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", - log_block_get_hdr_no(block), - log_block_get_checkpoint_no(block), - log_block_calc_checksum(block), - log_block_get_checksum(block)); + if (print_err) { + fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(block), + log_block_get_checkpoint_no(block), + log_block_calc_checksum(block), + log_block_get_checksum(block)); + } return(FALSE); } @@ -2734,6 +2737,7 @@ recv_scan_log_recs( ibool finished; ulint data_len; ibool more_data; + bool maybe_encrypted=false; ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); @@ -2748,6 +2752,8 @@ recv_scan_log_recs( *err = DB_SUCCESS; do { + log_crypt_err_t log_crypt_err; + no = log_block_get_hdr_no(log_block); /* fprintf(stderr, "Log block header no %lu\n", no); @@ -2755,13 +2761,13 @@ recv_scan_log_recs( fprintf(stderr, "Scanned lsn no %lu\n", log_block_convert_lsn_to_no(scanned_lsn)); */ + if (no != log_block_convert_lsn_to_no(scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { - log_crypt_err_t log_crypt_err; + || !log_block_checksum_is_ok_or_old_format(log_block, true)) { if (no == log_block_convert_lsn_to_no(scanned_lsn) && !log_block_checksum_is_ok_or_old_format( - log_block)) { + log_block, true)) { fprintf(stderr, "InnoDB: Log block no %lu at" " lsn " LSN_PF " has\n" @@ -2775,12 +2781,14 @@ recv_scan_log_recs( log_block)); } + maybe_encrypted = log_crypt_block_maybe_encrypted(log_block, + &log_crypt_err); + /* Garbage or an incompletely written log block */ finished = TRUE; - if (log_crypt_block_maybe_encrypted(log_block, - &log_crypt_err)) { + if (maybe_encrypted) { /* Log block maybe encrypted finish processing*/ log_crypt_print_error(log_crypt_err); *err = DB_ERROR; @@ -2790,12 +2798,13 @@ recv_scan_log_recs( /* Stop if we encounter a garbage log block */ if (!srv_force_recovery) { fputs("InnoDB: Set innodb_force_recovery" - " to ignore this error.\n", stderr); + " to ignore this error.\n", stderr); *err = DB_ERROR; return (TRUE); } break; + } if (log_block_get_flush_bit(log_block)) { |