diff options
-rw-r--r-- | include/handler_ername.h | 1 | ||||
-rw-r--r-- | include/my_base.h | 6 | ||||
-rw-r--r-- | include/my_handler_errors.h | 3 | ||||
-rw-r--r-- | mysql-test/include/wait_until_connected_again.inc | 6 | ||||
-rw-r--r-- | mysql-test/suite/maria/encrypt-no-key.result | 36 | ||||
-rw-r--r-- | mysql-test/suite/maria/encrypt-no-key.test | 55 | ||||
-rw-r--r-- | mysql-test/suite/maria/encrypt-wrong-key.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/maria/encrypt-wrong-key.test | 7 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 3 | ||||
-rw-r--r-- | storage/maria/ma_create.c | 2 | ||||
-rw-r--r-- | storage/maria/ma_crypt.c | 35 | ||||
-rw-r--r-- | storage/maria/ma_crypt.h | 3 | ||||
-rw-r--r-- | storage/maria/ma_delete_table.c | 7 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 3 |
14 files changed, 135 insertions, 44 deletions
diff --git a/include/handler_ername.h b/include/handler_ername.h index fe55062e6fb..20e62487c2c 100644 --- a/include/handler_ername.h +++ b/include/handler_ername.h @@ -79,3 +79,4 @@ { "HA_ERR_ABORTED_BY_USER", HA_ERR_ABORTED_BY_USER, "" }, { "HA_ERR_DISK_FULL", HA_ERR_DISK_FULL, "" }, { "HA_ERR_INCOMPATIBLE_DEFINITION", HA_ERR_INCOMPATIBLE_DEFINITION, "" }, +{ "HA_ERR_NO_ENCRYPTION", HA_ERR_NO_ENCRYPTION, "" }, diff --git a/include/my_base.h b/include/my_base.h index 32ef6f7fe85..cc3d57cb0b1 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -48,6 +48,7 @@ #define HA_OPEN_NO_PSI_CALL 1024U /* Don't call/connect PSI */ #define HA_OPEN_MERGE_TABLE 2048U #define HA_OPEN_FOR_CREATE 4096U +#define HA_OPEN_FOR_DROP (1U << 13) /* Open part of drop */ /* Allow opening even if table is incompatible as this is for ALTER TABLE which @@ -516,14 +517,15 @@ enum ha_base_keytype { #define HA_ERR_DISK_FULL 189 #define HA_ERR_INCOMPATIBLE_DEFINITION 190 #define HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE 191 /* Too many words in a phrase */ -#define HA_ERR_DECRYPTION_FAILED 192 /* Table encrypted but decypt failed */ +#define HA_ERR_DECRYPTION_FAILED 192 /* Table encrypted but decrypt failed */ #define HA_ERR_FK_DEPTH_EXCEEDED 193 /* FK cascade depth exceeded */ #define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */ #define HA_ERR_SEQUENCE_INVALID_DATA 195 #define HA_ERR_SEQUENCE_RUN_OUT 196 #define HA_ERR_COMMIT_ERROR 197 #define HA_ERR_PARTITION_LIST 198 -#define HA_ERR_LAST 198 /* Copy of last error nr * */ +#define HA_ERR_NO_ENCRYPTION 199 +#define HA_ERR_LAST 199 /* Copy of last error nr * */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_handler_errors.h b/include/my_handler_errors.h index 4c3a02dd745..7eab185dd98 100644 --- a/include/my_handler_errors.h +++ b/include/my_handler_errors.h @@ -109,7 +109,8 @@ static const char *handler_error_messages[]= "Sequence has been run out", "Sequence values are conflicting", "Error during commit", - "Cannot select partitions" + "Cannot select partitions", + "Cannot initialize encryption. Check that all encryption parameters have been set" }; #endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/mysql-test/include/wait_until_connected_again.inc b/mysql-test/include/wait_until_connected_again.inc index 15a1e5bf847..f644ec8645f 100644 --- a/mysql-test/include/wait_until_connected_again.inc +++ b/mysql-test/include/wait_until_connected_again.inc @@ -11,7 +11,7 @@ let $counter= 5000; let $mysql_errno= 9999; while ($mysql_errno) { - --error 0,ER_ACCESS_DENIED_ERROR,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013 + --error 0,ER_ACCESS_DENIED_ERROR,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013,HA_ERR_NO_ENCRYPTION show status; dec $counter; @@ -30,6 +30,10 @@ while ($mysql_errno) { let $mysql_errno=0; } + if ($mysql_errno == 199) + { + let $mysql_errno=0; + } --sleep 0.1 } --enable_query_log diff --git a/mysql-test/suite/maria/encrypt-no-key.result b/mysql-test/suite/maria/encrypt-no-key.result index 6745670dfac..32a280d8cbc 100644 --- a/mysql-test/suite/maria/encrypt-no-key.result +++ b/mysql-test/suite/maria/encrypt-no-key.result @@ -1,15 +1,27 @@ -call mtr.add_suppression('Unknown key id 1. Can''t continue'); +call mtr.add_suppression("Initialization of encryption failed.*"); set global aria_encrypt_tables= 1; create table t1 (pk int primary key, a int, key(a)) engine=aria transactional=1; -alter table t1 disable keys; -insert into t1 values (1,1); -alter table t1 enable keys; -ERROR HY000: Unknown key id 1. Can't continue! -repair table t1 use_frm; -Table Op Msg_type Msg_text -test.t1 repair warning Number of rows changed from 0 to 1 -test.t1 repair Error Unknown key id 1. Can't continue! -test.t1 repair Error Unknown key id 1. Can't continue! -test.t1 repair status OK -drop table t1; +ERROR HY000: Initialization of encryption failed for ./test/t1 set global aria_encrypt_tables= default; +# +# MDEV-26258 Various crashes/asserts/corruptions when Aria encryption is +# enabled/used, but the encryption plugin is not loaded +# +SET GLOBAL aria_encrypt_tables=ON; +CREATE TABLE t1 (a INT KEY,b INT,KEY(b)) ENGINE=Aria; +ERROR HY000: Initialization of encryption failed for ./test/t1 +# Restart with encryption enabled +CREATE TABLE t1 (a INT KEY,b INT,KEY(b)) ENGINE=Aria; +INSERT INTO t1 VALUES (4,0); +LOAD INDEX INTO CACHE t1 IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +LOAD INDEX INTO CACHE t1; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +SELECT * FROM t1; +ERROR HY000: Initialization of encryption failed for ./test/t1.MAD +DROP TABLE t1; +Warnings: +Warning 199 Initialization of encryption failed for ./test/t1.MAD +Cleanup diff --git a/mysql-test/suite/maria/encrypt-no-key.test b/mysql-test/suite/maria/encrypt-no-key.test index 2d586c50695..b3f2f4b4bf3 100644 --- a/mysql-test/suite/maria/encrypt-no-key.test +++ b/mysql-test/suite/maria/encrypt-no-key.test @@ -1,14 +1,55 @@ # # MDEV-18496 Crash when Aria encryption is enabled but plugin not available # -call mtr.add_suppression('Unknown key id 1. Can''t continue'); +call mtr.add_suppression("Initialization of encryption failed.*"); set global aria_encrypt_tables= 1; +--error HA_ERR_NO_ENCRYPTION create table t1 (pk int primary key, a int, key(a)) engine=aria transactional=1; -alter table t1 disable keys; -insert into t1 values (1,1); -error 192; -alter table t1 enable keys; -repair table t1 use_frm; -drop table t1; set global aria_encrypt_tables= default; + +--echo # +--echo # MDEV-26258 Various crashes/asserts/corruptions when Aria encryption is +--echo # enabled/used, but the encryption plugin is not loaded +--echo # + +SET GLOBAL aria_encrypt_tables=ON; + +--write_file $MYSQLTEST_VARDIR/keys1.txt +1;770A8A65DA156D24EE2A093277530142 +EOF + +--replace_result \\ / +--error HA_ERR_NO_ENCRYPTION +CREATE TABLE t1 (a INT KEY,b INT,KEY(b)) ENGINE=Aria; + +--echo # Restart with encryption enabled + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc +--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +CREATE TABLE t1 (a INT KEY,b INT,KEY(b)) ENGINE=Aria; +INSERT INTO t1 VALUES (4,0); +LOAD INDEX INTO CACHE t1 IGNORE LEAVES; +LOAD INDEX INTO CACHE t1; + +# Restart without encryption. Above table should be unreadable + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc +--exec echo "restart:--aria-encrypt-tables=0" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_result \\ / +--error HA_ERR_NO_ENCRYPTION +SELECT * FROM t1; +DROP TABLE t1; + +--echo Cleanup +--remove_file $MYSQLTEST_VARDIR/keys1.txt diff --git a/mysql-test/suite/maria/encrypt-wrong-key.result b/mysql-test/suite/maria/encrypt-wrong-key.result index bc22481296d..4ff057957da 100644 --- a/mysql-test/suite/maria/encrypt-wrong-key.result +++ b/mysql-test/suite/maria/encrypt-wrong-key.result @@ -1,16 +1,16 @@ call mtr.add_suppression("file_key_management"); call mtr.add_suppression("System key id 1 is missing"); call mtr.add_suppression("Unknown key id 1"); -call mtr.add_suppression("Failed to decrypt"); +call mtr.add_suppression("Initialization of encryption failed.*"); CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria; INSERT INTO t1 VALUES (1); repair table t1; Table Op Msg_type Msg_text -test.t1 repair info Wrong CRC on datapage at 1 -test.t1 repair warning Number of rows changed from 1 to 0 -test.t1 repair status OK +test.t1 repair Error Initialization of encryption failed for ./test/t1.MAD +test.t1 repair error Corrupt INSERT INTO t1 VALUES (2); +ERROR HY000: Initialization of encryption failed for ./test/t1.MAD select * from t1; -ERROR HY000: failed to decrypt './test/t1' rc: -1 dstlen: 0 size: 8172 - +i +1 drop table t1; diff --git a/mysql-test/suite/maria/encrypt-wrong-key.test b/mysql-test/suite/maria/encrypt-wrong-key.test index ca65e1018d0..ac060c4e9dd 100644 --- a/mysql-test/suite/maria/encrypt-wrong-key.test +++ b/mysql-test/suite/maria/encrypt-wrong-key.test @@ -7,7 +7,7 @@ call mtr.add_suppression("file_key_management"); call mtr.add_suppression("System key id 1 is missing"); call mtr.add_suppression("Unknown key id 1"); -call mtr.add_suppression("Failed to decrypt"); +call mtr.add_suppression("Initialization of encryption failed.*"); --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server @@ -36,8 +36,11 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc +--replace_result \\ / repair table t1; +--replace_result \\ / +--error HA_ERR_NO_ENCRYPTION INSERT INTO t1 VALUES (2); --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect @@ -48,8 +51,6 @@ INSERT INTO t1 VALUES (2); --enable_reconnect --source include/wait_until_connected_again.inc ---replace_result \\ / ---error 192 select * from t1; drop table t1; --remove_file $MYSQLTEST_VARDIR/keys1.txt diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 2d6c8f85fe4..f25ba2aa0b3 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -292,7 +292,8 @@ static MYSQL_SYSVAR_BOOL(used_for_temp_tables, "Whether temporary tables should be MyISAM or Aria", 0, 0, 1); -static MYSQL_SYSVAR_BOOL(encrypt_tables, maria_encrypt_tables, PLUGIN_VAR_OPCMDARG, +static MYSQL_SYSVAR_BOOL(encrypt_tables, maria_encrypt_tables, + PLUGIN_VAR_OPCMDARG, "Encrypt tables (only for tables with ROW_FORMAT=PAGE (default) " "and not FIXED/DYNAMIC)", 0, 0, 0); diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 8ef3249c2e4..3352a494d16 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -1062,6 +1062,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, if (encrypted) { + DBUG_ASSERT(share.data_file_name.length == 0); + share.data_file_name.str= (char*) name; /* For error reporting */ if (ma_crypt_create(&share) || ma_crypt_write(&share, file)) goto err; diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index 33cf72b0b1e..8cc85d87d28 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -100,6 +100,7 @@ static void crypt_data_scheme_locker(struct st_encryption_scheme *scheme, int ma_crypt_create(MARIA_SHARE* share) { + uint key_version; MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL)); crypt_data->scheme.type= CRYPT_SCHEME_1; @@ -110,6 +111,16 @@ ma_crypt_create(MARIA_SHARE* share) my_random_bytes((uchar*)&crypt_data->space, sizeof(crypt_data->space)); share->crypt_data= crypt_data; share->crypt_page_header_space= CRYPT_SCHEME_1_KEY_VERSION_SIZE; + + key_version = encryption_key_get_latest_version(crypt_data->scheme.key_id); + if (unlikely(key_version == ENCRYPTION_KEY_VERSION_INVALID)) + { + my_errno= HA_ERR_NO_ENCRYPTION; + my_printf_error(HA_ERR_NO_ENCRYPTION, + "Initialization of encryption failed for %s", MYF(0), + share->data_file_name.str); + return 1; + } return 0; } @@ -145,7 +156,7 @@ ma_crypt_write(MARIA_SHARE* share, File file) } uchar* -ma_crypt_read(MARIA_SHARE* share, uchar *buff) +ma_crypt_read(MARIA_SHARE* share, uchar *buff, my_bool silent) { uchar type= buff[0]; uchar iv_length= buff[1]; @@ -155,9 +166,9 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) iv_length != sizeof(((MARIA_CRYPT_DATA*)1)->scheme.iv) + 4) { my_printf_error(HA_ERR_UNSUPPORTED, - "Unsupported crypt scheme! type: %d iv_length: %d\n", - MYF(ME_FATAL|ME_ERROR_LOG), - type, iv_length); + "Unsupported crypt scheme type: %d iv_length: %d\n", + MYF(ME_ERROR_LOG | (silent ? ME_WARNING : ME_FATAL)), + type, iv_length); return 0; } @@ -166,6 +177,7 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) /* opening a table */ MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL)); + uint key_version; crypt_data->scheme.type= type; mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock, @@ -175,6 +187,17 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) crypt_data->space= uint4korr(buff + 2); memcpy(crypt_data->scheme.iv, buff + 6, sizeof(crypt_data->scheme.iv)); share->crypt_data= crypt_data; + + key_version= encryption_key_get_latest_version(crypt_data->scheme.key_id); + if (unlikely(key_version == ENCRYPTION_KEY_VERSION_INVALID)) + { + my_errno= HA_ERR_NO_ENCRYPTION; + my_printf_error(HA_ERR_NO_ENCRYPTION, + "Initialization of encryption failed for %s", + MYF(ME_ERROR_LOG | (silent ? ME_WARNING : ME_FATAL)), + share->data_file_name.str); + return 0; + } } share->crypt_page_header_space= CRYPT_SCHEME_1_KEY_VERSION_SIZE; @@ -462,7 +485,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, uint32 dstlen= 0; /* Must be set because of error message */ *key_version = encryption_key_get_latest_version(crypt_data->scheme.key_id); - if (*key_version == ENCRYPTION_KEY_VERSION_INVALID) + if (unlikely(*key_version == ENCRYPTION_KEY_VERSION_INVALID)) { /* We use this error for both encryption and decryption, as in normal @@ -470,7 +493,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, */ my_errno= HA_ERR_DECRYPTION_FAILED; my_printf_error(HA_ERR_DECRYPTION_FAILED, - "Unknown key id %u. Can't continue!", + "Unknown encryption key id %u. Can't continue!", MYF(ME_FATAL|ME_ERROR_LOG), crypt_data->scheme.key_id); return 1; diff --git a/storage/maria/ma_crypt.h b/storage/maria/ma_crypt.h index 811b319bc0c..acaf36ee831 100644 --- a/storage/maria/ma_crypt.h +++ b/storage/maria/ma_crypt.h @@ -26,7 +26,8 @@ uint ma_crypt_get_index_page_header_space(struct st_maria_share *); uint ma_crypt_get_file_length(); /* bytes needed in file */ int ma_crypt_create(struct st_maria_share *); /* create encryption data */ int ma_crypt_write(struct st_maria_share *, File); /* write encryption data */ -uchar* ma_crypt_read(struct st_maria_share *, uchar *buff); /* read crypt data*/ +uchar* ma_crypt_read(struct st_maria_share *, uchar *buff, + my_bool silent); /* read crypt data*/ void ma_crypt_set_data_pagecache_callbacks(struct st_pagecache_file *file, struct st_maria_share *share); diff --git a/storage/maria/ma_delete_table.c b/storage/maria/ma_delete_table.c index 0c78476ad44..250ea9dff89 100644 --- a/storage/maria/ma_delete_table.c +++ b/storage/maria/ma_delete_table.c @@ -43,12 +43,13 @@ int maria_delete_table(const char *name) 'open_for_repair' to be able to open even a crashed table. */ my_errno= 0; - if (!(info= maria_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) + if (!(info= maria_open(name, O_RDONLY, (HA_OPEN_FOR_DROP | HA_OPEN_FOR_REPAIR)))) { sync_dir= 0; /* Ignore not found errors and wrong symlink errors */ - if (my_errno != ENOENT && my_errno != HA_WRONG_CREATE_OPTION) - got_error= my_errno;; + if (my_errno != ENOENT && my_errno != HA_WRONG_CREATE_OPTION && + my_errno != HA_ERR_NO_ENCRYPTION) + got_error= my_errno; } else { diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 06183c72895..7b59351e24b 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -863,7 +863,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if (MY_TEST(share->base.extra_options & MA_EXTRA_OPTIONS_ENCRYPTED)) { - if (!(disk_pos= ma_crypt_read(share, disk_pos))) + if (!(disk_pos= ma_crypt_read(share, disk_pos, + MY_TEST(open_flags & HA_OPEN_FOR_DROP)))) goto err; } |