summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2023-03-16 17:24:12 +0200
committerMonty <monty@mariadb.org>2023-05-02 23:37:10 +0300
commit1ef22e28ad7744d436c694e970420c426fc7095a (patch)
tree8f9b29b86da5f470ce7a0c849ce3e0c1a16f1b2a
parentc6ef9b1c1a59dd5dae81888d47f1749e1a433b96 (diff)
downloadmariadb-git-1ef22e28ad7744d436c694e970420c426fc7095a.tar.gz
MDEV-26258 Various crashes/asserts/corruptions when Aria encryption is enabled/used, but the encryption plugin is not loaded
The reason for the MDEV reported failures is that the tests are enabling encryption for Aria but not providing any encryption keys. Fixed by checking if encryption keys exists before creating the table. Other things: - maria.encrypt_wrong-key changed as we now get the error on CREATE instead during insert.
-rw-r--r--include/handler_ername.h1
-rw-r--r--include/my_base.h6
-rw-r--r--include/my_handler_errors.h3
-rw-r--r--mysql-test/include/wait_until_connected_again.inc6
-rw-r--r--mysql-test/suite/maria/encrypt-no-key.result36
-rw-r--r--mysql-test/suite/maria/encrypt-no-key.test55
-rw-r--r--mysql-test/suite/maria/encrypt-wrong-key.result12
-rw-r--r--mysql-test/suite/maria/encrypt-wrong-key.test7
-rw-r--r--storage/maria/ha_maria.cc3
-rw-r--r--storage/maria/ma_create.c2
-rw-r--r--storage/maria/ma_crypt.c35
-rw-r--r--storage/maria/ma_crypt.h3
-rw-r--r--storage/maria/ma_delete_table.c7
-rw-r--r--storage/maria/ma_open.c3
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;
}