diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-08-16 09:53:27 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-09-04 20:19:33 +0300 |
commit | e1978234ebe6606c3ad5a0d1be6ce0f86fcf7642 (patch) | |
tree | a44bb09038c82aa69fa727582faebf1ec9f32abe /storage/innobase | |
parent | e9b6f95013b0db125c616269d747a0c365f5f5c8 (diff) | |
download | mariadb-git-e1978234ebe6606c3ad5a0d1be6ce0f86fcf7642.tar.gz |
MDEV-8588: Assertion failure in file ha_innodb.cc line 21140 if at least one encrypted table exists and encryption service is not available
Analysis: Problem was that in fil_read_first_page we do find that
table has encryption information and that encryption service
or used key_id is not available. But, then we just printed
fatal error message that causes above assertion.
Fix: When we open single table tablespace if it has encryption
information (crypt_data) store this crypt data to the table
structure. When we open a table and we find out that tablespace
is not available, check has table a encryption information
and from there is encryption service or used key_id is not available.
If it is, add additional warning for SQL-layer.
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/dict/dict0load.cc | 4 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 44 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 20 | ||||
-rw-r--r-- | storage/innobase/include/dict0mem.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 6 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 2 |
6 files changed, 63 insertions, 17 deletions
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 149811dab60..d8bd0a66ade 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1168,7 +1168,7 @@ loop: dberr_t err = fil_open_single_table_tablespace( read_page_0, srv_read_only_mode ? false : true, space_id, dict_tf_to_fsp_flags(flags), - name, filepath); + name, filepath, NULL); if (err != DB_SUCCESS) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2412,7 +2412,7 @@ err_exit: err = fil_open_single_table_tablespace( true, false, table->space, dict_tf_to_fsp_flags(table->flags), - name, filepath); + name, filepath, table); if (err != DB_SUCCESS) { /* We failed to find a sensible diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0768496a6bb..831a3319eff 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1986,6 +1986,7 @@ fil_read_first_page( const char* check_msg = NULL; fil_space_crypt_t* cdata; + buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE)); /* Align the memory for a possible read from a raw device */ @@ -2015,6 +2016,10 @@ fil_read_first_page( fsp_flags_get_zip_size(*flags), NULL); cdata = fil_space_read_crypt_data(space, page, offset); + if (crypt_data) { + *crypt_data = cdata; + } + /* If file space is encrypted we need to have at least some encryption service available where to get keys */ if ((cdata && cdata->encryption == FIL_SPACE_ENCRYPTION_ON) || @@ -2022,16 +2027,14 @@ fil_read_first_page( cdata && cdata->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) { if (!encryption_key_id_exists(cdata->key_id)) { - ib_logf(IB_LOG_LEVEL_FATAL, - "Tablespace id %ld encrypted but encryption service" - " not available. Can't continue opening tablespace.\n", - space); - ut_error; - } - } + ib_logf(IB_LOG_LEVEL_ERROR, + "Tablespace id %ld is encrypted but encryption service" + " or used key_id %u is not available. Can't continue opening tablespace.", + space, cdata->key_id); - if (crypt_data) { - *crypt_data = cdata; + return ("table encrypted but encryption service not available."); + + } } ut_free(buf); @@ -3621,7 +3624,8 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: tablespace flags */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* path_in) /*!< in: tablespace filepath */ + const char* path_in, /*!< in: tablespace filepath */ + dict_table_t* table) /*!< in: table */ { dberr_t err = DB_SUCCESS; bool dict_filepath_same_as_default = false; @@ -3738,6 +3742,10 @@ fil_open_single_table_tablespace( &def.lsn, &def.lsn, &def.crypt_data); def.valid = !def.check_msg; + if (table) { + table->crypt_data = def.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3763,6 +3771,10 @@ fil_open_single_table_tablespace( &remote.lsn, &remote.lsn, &remote.crypt_data); remote.valid = !remote.check_msg; + if (table) { + table->crypt_data = remote.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3789,6 +3801,10 @@ fil_open_single_table_tablespace( &dict.lsn, &dict.lsn, &dict.crypt_data); dict.valid = !dict.check_msg; + if (table) { + table->crypt_data = dict.crypt_data; + } + /* Validate this single-table-tablespace with SYS_TABLES, but do not compare the DATA_DIR flag, in case the tablespace was relocated. */ @@ -3970,7 +3986,9 @@ cleanup_and_exit: mem_free(remote.filepath); } if (remote.crypt_data && remote.crypt_data != crypt_data) { - fil_space_destroy_crypt_data(&remote.crypt_data); + if (err == DB_SUCCESS) { + fil_space_destroy_crypt_data(&remote.crypt_data); + } } if (dict.success) { os_file_close(dict.file); @@ -3985,7 +4003,9 @@ cleanup_and_exit: os_file_close(def.file); } if (def.crypt_data && def.crypt_data != crypt_data) { - fil_space_destroy_crypt_data(&def.crypt_data); + if (err == DB_SUCCESS) { + fil_space_destroy_crypt_data(&def.crypt_data); + } } mem_free(def.filepath); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b07c756e81f..6722ee85428 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5629,6 +5629,26 @@ table_opened: free_share(share); my_errno = ENOENT; + /* If table has no talespace but it has crypt data, check + is tablespace made unaccessible because encryption service + or used key_id is not available. */ + if (ib_table && ib_table->crypt_data) { + fil_space_crypt_t* crypt_data = ib_table->crypt_data; + if ((crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) || + (srv_encrypt_tables && + crypt_data && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) { + + if (!encryption_key_id_exists(crypt_data->key_id)) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_NO_SUCH_TABLE, + "Table %s is encrypted but encryption service or" + " used key_id %u is not available. " + " Can't continue reading table.", + ib_table->name, crypt_data->key_id); + } + } + } + dict_table_close(ib_table, FALSE, FALSE); DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 24db728ae08..059ba2208e3 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -48,6 +48,9 @@ Created 1/8/1996 Heikki Tuuri #include "trx0types.h" #include "fts0fts.h" #include "os0once.h" +#include "fil0fil.h" +#include <my_crypt.h> +#include "fil0crypt.h" #include <set> #include <algorithm> #include <iterator> @@ -1014,6 +1017,7 @@ struct dict_table_t{ table_id_t id; /*!< id of the table */ mem_heap_t* heap; /*!< memory heap */ char* name; /*!< table name */ + fil_space_crypt_t *crypt_data; /*!< crypt data if present */ const char* dir_path_of_temp_table;/*!< NULL or the directory path where a TEMPORARY table that was explicitly created by a user should be placed if diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 93ff999bcfe..e842049e734 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -213,7 +213,8 @@ struct fsp_open_info { #ifdef UNIV_LOG_ARCHIVE ulint arch_log_no; /*!< latest archived log file number */ #endif /* UNIV_LOG_ARCHIVE */ - fil_space_crypt_t* crypt_data; /*!< crypt data */ + fil_space_crypt_t* crypt_data; /*!< crypt data */ + dict_table_t* table; /*!< table */ }; struct fil_space_t; @@ -833,7 +834,8 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: tablespace flags */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* filepath) /*!< in: tablespace filepath */ + const char* filepath, /*!< in: tablespace filepath */ + dict_table_t* table) /*!< in: table */ __attribute__((nonnull(5), warn_unused_result)); #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 93804e4da39..4034a228153 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3628,7 +3628,7 @@ row_import_for_mysql( err = fil_open_single_table_tablespace( true, true, table->space, dict_tf_to_fsp_flags(table->flags), - table->name, filepath); + table->name, filepath, table); DBUG_EXECUTE_IF("ib_import_open_tablespace_failure", err = DB_TABLESPACE_NOT_FOUND;); |