summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2018-03-13 10:12:24 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2018-03-13 10:12:24 +0200
commitb4026efaacbfc935d3ce8fc0fdb0a88920c4f426 (patch)
tree9be9e1505cf388b2041bd463e70ef19786ad816c
parent72a877d7200edb7de1b2730d4df79fc1d36b30ab (diff)
downloadmariadb-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.ibdbin0 -> 98304 bytes
-rw-r--r--mysql-test/std_data/t1_le.ibdbin0 -> 98304 bytes
-rw-r--r--mysql-test/std_data/t2_be.ibdbin0 -> 65536 bytes
-rw-r--r--mysql-test/std_data/t2_le.ibdbin0 -> 65536 bytes
-rw-r--r--mysql-test/suite/encryption/r/innodb-import.result32
-rw-r--r--mysql-test/suite/encryption/t/innodb-import.opt4
-rw-r--r--mysql-test/suite/encryption/t/innodb-import.test54
-rw-r--r--storage/innobase/fil/fil0fil.cc32
-rw-r--r--storage/xtradb/fil/fil0fil.cc32
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
new file mode 100644
index 00000000000..4cd8ab436da
--- /dev/null
+++ b/mysql-test/std_data/t1_be.ibd
Binary files differ
diff --git a/mysql-test/std_data/t1_le.ibd b/mysql-test/std_data/t1_le.ibd
new file mode 100644
index 00000000000..ad763a0f08f
--- /dev/null
+++ b/mysql-test/std_data/t1_le.ibd
Binary files differ
diff --git a/mysql-test/std_data/t2_be.ibd b/mysql-test/std_data/t2_be.ibd
new file mode 100644
index 00000000000..a763a38b79e
--- /dev/null
+++ b/mysql-test/std_data/t2_be.ibd
Binary files differ
diff --git a/mysql-test/std_data/t2_le.ibd b/mysql-test/std_data/t2_le.ibd
new file mode 100644
index 00000000000..2668a1ac91e
--- /dev/null
+++ b/mysql-test/std_data/t2_le.ibd
Binary files differ
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);