diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-03-13 10:12:24 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-03-13 10:12:24 +0200 |
commit | b4026efaacbfc935d3ce8fc0fdb0a88920c4f426 (patch) | |
tree | 9be9e1505cf388b2041bd463e70ef19786ad816c | |
parent | 72a877d7200edb7de1b2730d4df79fc1d36b30ab (diff) | |
download | mariadb-git-bb-10.1-MDEV-15032.tar.gz |
MDEV-15032: Encrypted database created on big endian machine cannot be used on little endian machinebb-10.1-MDEV-15032
Problem was that uc_crc32 was not byte order agnostic.
fil_iterate
Check post encryption checksum before actual decryption.
Add test case to import both little-endian and big-endian tables that
use encryption.
-rw-r--r-- | mysql-test/std_data/t1_be.ibd | bin | 0 -> 98304 bytes | |||
-rw-r--r-- | mysql-test/std_data/t1_le.ibd | bin | 0 -> 98304 bytes | |||
-rw-r--r-- | mysql-test/std_data/t2_be.ibd | bin | 0 -> 65536 bytes | |||
-rw-r--r-- | mysql-test/std_data/t2_le.ibd | bin | 0 -> 65536 bytes | |||
-rw-r--r-- | mysql-test/suite/encryption/r/innodb-import.result | 32 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-import.opt | 4 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-import.test | 54 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 32 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0fil.cc | 32 |
9 files changed, 144 insertions, 10 deletions
diff --git a/mysql-test/std_data/t1_be.ibd b/mysql-test/std_data/t1_be.ibd Binary files differnew file mode 100644 index 00000000000..4cd8ab436da --- /dev/null +++ b/mysql-test/std_data/t1_be.ibd diff --git a/mysql-test/std_data/t1_le.ibd b/mysql-test/std_data/t1_le.ibd Binary files differnew file mode 100644 index 00000000000..ad763a0f08f --- /dev/null +++ b/mysql-test/std_data/t1_le.ibd diff --git a/mysql-test/std_data/t2_be.ibd b/mysql-test/std_data/t2_be.ibd Binary files differnew file mode 100644 index 00000000000..a763a38b79e --- /dev/null +++ b/mysql-test/std_data/t2_be.ibd diff --git a/mysql-test/std_data/t2_le.ibd b/mysql-test/std_data/t2_le.ibd Binary files differnew file mode 100644 index 00000000000..2668a1ac91e --- /dev/null +++ b/mysql-test/std_data/t2_le.ibd diff --git a/mysql-test/suite/encryption/r/innodb-import.result b/mysql-test/suite/encryption/r/innodb-import.result new file mode 100644 index 00000000000..1b4ec053d21 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb-import.result @@ -0,0 +1,32 @@ +call mtr.add_suppression("InnoDB: Table \'\"test\".\"t[1-2]_[l|b]e\"\' tablespace is set as discarded."); +SET GLOBAL innodb_file_format = `Barracuda`; +create table t1_le(a int) engine=innodb encrypted=yes; +create table t2_le(a int) engine=innodb row_format=compressed encrypted=yes; +create table t1_be(a int) engine=innodb encrypted=yes; +create table t2_be(a int) engine=innodb row_format=compressed encrypted=yes; +ALTER TABLE t1_le DISCARD TABLESPACE; +ALTER TABLE t2_le DISCARD TABLESPACE; +ALTER TABLE t1_be DISCARD TABLESPACE; +ALTER TABLE t2_be DISCARD TABLESPACE; +ALTER TABLE t1_le IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1_le.cfg', will attempt to import without schema verification +ALTER TABLE t1_be IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1_be.cfg', will attempt to import without schema verification +ALTER TABLE t2_le IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t2_le.cfg', will attempt to import without schema verification +ALTER TABLE t2_be IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t2_be.cfg', will attempt to import without schema verification +select * from t1_le; +a +select * from t1_be; +a +select * from t2_le; +a +select * from t2_be; +a +drop table t1_le, t1_be, t2_le, t2_be; +SET GLOBAL innodb_file_format = Default; diff --git a/mysql-test/suite/encryption/t/innodb-import.opt b/mysql-test/suite/encryption/t/innodb-import.opt new file mode 100644 index 00000000000..510ebebd1af --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-import.opt @@ -0,0 +1,4 @@ +--plugin-load-add=$FILE_KEY_MANAGEMENT_SO +--loose-file-key-management +--loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt +--file-key-management-encryption-algorithm=aes_cbc diff --git a/mysql-test/suite/encryption/t/innodb-import.test b/mysql-test/suite/encryption/t/innodb-import.test new file mode 100644 index 00000000000..ab4c20f3ea5 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-import.test @@ -0,0 +1,54 @@ +--source include/have_innodb.inc +--source include/have_file_key_management_plugin.inc + +# +# MDEV-15032 Encrypted database created on big endian machine cannot be used on little endian machine +# + +call mtr.add_suppression("InnoDB: Table \'\"test\".\"t[1-2]_[l|b]e\"\' tablespace is set as discarded."); + +--disable_warnings +SET GLOBAL innodb_file_format = `Barracuda`; +--enable_warnings + +create table t1_le(a int) engine=innodb encrypted=yes; +create table t2_le(a int) engine=innodb row_format=compressed encrypted=yes; +create table t1_be(a int) engine=innodb encrypted=yes; +create table t2_be(a int) engine=innodb row_format=compressed encrypted=yes; + +# +# TODO: In MDEV-13103 InnoDB crash recovery fails to decompress a page in buf_dblwr_process() +# add page compressed tables. +# + +ALTER TABLE t1_le DISCARD TABLESPACE; +ALTER TABLE t2_le DISCARD TABLESPACE; +ALTER TABLE t1_be DISCARD TABLESPACE; +ALTER TABLE t2_be DISCARD TABLESPACE; + +let $MYSQLD_DATADIR =`SELECT @@datadir`; + +# +# Copy exported datafiles +# + +--copy_file std_data/t1_le.ibd $MYSQLD_DATADIR/test/t1_le.ibd +--copy_file std_data/t1_be.ibd $MYSQLD_DATADIR/test/t1_be.ibd +--copy_file std_data/t2_le.ibd $MYSQLD_DATADIR/test/t2_le.ibd +--copy_file std_data/t2_be.ibd $MYSQLD_DATADIR/test/t2_be.ibd + +ALTER TABLE t1_le IMPORT TABLESPACE; +ALTER TABLE t1_be IMPORT TABLESPACE; +ALTER TABLE t2_le IMPORT TABLESPACE; +ALTER TABLE t2_be IMPORT TABLESPACE; + +select * from t1_le; +select * from t1_be; +select * from t2_le; +select * from t2_be; + +drop table t1_le, t1_be, t2_le, t2_be; + +--disable_warnings +SET GLOBAL innodb_file_format = Default; +--enable_warnings diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0cdbee09548..8c7762c82c3 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -6449,7 +6449,6 @@ fil_iterate( bool updated = false; os_offset_t page_off = offset; ulint n_pages_read = (ulint) n_bytes / iter.page_size; - bool decrypted = false; for (ulint i = 0; i < n_pages_read; ++i) { ulint size = iter.page_size; @@ -6457,8 +6456,10 @@ fil_iterate( byte* src = readptr + (i * size); byte* dst = io_buffer + (i * size); bool frame_changed = false; + bool decrypted = false; ulint page_type = mach_read_from_2(src+FIL_PAGE_TYPE); + uint key_version = mach_read_from_4(src+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); const bool page_compressed = page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED @@ -6468,12 +6469,33 @@ fil_iterate( the page. Note that tablespaces are not in fil_system during import. */ if (encrypted) { - decrypted = fil_space_decrypt( + if (key_version) { + /* Verify post encryption checksum before + actual decrypt. */ + if (fil_space_verify_crypt_checksum(src, + callback.get_zip_size(), + NULL, + page_no)) { + decrypted = fil_space_decrypt( iter.crypt_data, - dst, //dst + dst, iter.page_size, - src, // src - &err); // src + src, + &err); + } else { + ib_logf(IB_LOG_LEVEL_ERROR, + "Imported page [page id: space=" ULINTPF + ", page number=" ULINTPF "]" + " is corrupted. Post encryption" + " checksum " ULINTPF + " does not match calculated " ULINTPF ".", + space_id, page_no, + mach_read_from_4(src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4), + fil_crypt_calculate_checksum(callback.get_zip_size(), src)); + + err = DB_CORRUPTION; + } + } if (err != DB_SUCCESS) { return(err); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index e3a5a351edf..83c17bf113f 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -6794,7 +6794,6 @@ fil_iterate( bool updated = false; os_offset_t page_off = offset; ulint n_pages_read = (ulint) n_bytes / iter.page_size; - bool decrypted = false; for (ulint i = 0; i < n_pages_read; ++i) { ulint size = iter.page_size; @@ -6802,8 +6801,10 @@ fil_iterate( byte* src = readptr + (i * size); byte* dst = io_buffer + (i * size); bool frame_changed = false; + bool decrypted = false; ulint page_type = mach_read_from_2(src+FIL_PAGE_TYPE); + uint key_version = mach_read_from_4(src+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); const bool page_compressed = page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED @@ -6813,12 +6814,33 @@ fil_iterate( the page. Note that tablespaces are not in fil_system during import. */ if (encrypted) { - decrypted = fil_space_decrypt( + if (key_version) { + /* Verify post encryption checksum before + actual decrypt. */ + if (fil_space_verify_crypt_checksum(src, + callback.get_zip_size(), + NULL, + page_no)) { + decrypted = fil_space_decrypt( iter.crypt_data, - dst, //dst + dst, iter.page_size, - src, // src - &err); // src + src, + &err); + } else { + ib_logf(IB_LOG_LEVEL_ERROR, + "Imported page [page id: space=" ULINTPF + ", page number=" ULINTPF "]" + " is corrupted. Post encryption" + " checksum " ULINTPF + " does not match calculated " ULINTPF ".", + space_id, page_no, + mach_read_from_4(src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4), + fil_crypt_calculate_checksum(callback.get_zip_size(), src)); + + err = DB_CORRUPTION; + } + } if (err != DB_SUCCESS) { return(err); |