Skip to content

Commit

Permalink
MDEV-8589: Non-default ENCRYPTION_KEY_ID is ignored upon reading a table
Browse files Browse the repository at this point in the history
Analysis: Problem was that when a new tablespace is created a default
encryption info is also created and stored to the tablespace. Later a
new encryption information was created with correct key_id but that
does not affect on IV.

Fix: Push encryption mode and key_id to lower levels and create
correct encryption info when a new tablespace is created.

This fix does not contain test case because, currently incorrect
encryption key causes page corruption and a lot of error messages
to error log causing mtr to fail.
  • Loading branch information
Jan Lindström committed Aug 14, 2015
1 parent a807535 commit bfb6ea0
Show file tree
Hide file tree
Showing 22 changed files with 154 additions and 140 deletions.
10 changes: 7 additions & 3 deletions storage/innobase/dict/dict0crea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ dict_build_table_def_step(
space, table->name, path,
dict_tf_to_fsp_flags(table->flags),
table->flags2,
FIL_IBD_FILE_INITIAL_SIZE);
FIL_IBD_FILE_INITIAL_SIZE,
node->mode, node->key_id);

table->space = (unsigned int) space;

Expand Down Expand Up @@ -934,8 +935,10 @@ tab_create_graph_create(
dict_table_t* table, /*!< in: table to create, built as a memory data
structure */
mem_heap_t* heap, /*!< in: heap where created */
bool commit) /*!< in: true if the commit node should be
bool commit, /*!< in: true if the commit node should be
added to the query graph */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
tab_node_t* node;

Expand All @@ -948,6 +951,8 @@ tab_create_graph_create(

node->state = TABLE_BUILD_TABLE_DEF;
node->heap = mem_heap_create(256);
node->mode = mode;
node->key_id = key_id;

node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
heap);
Expand Down Expand Up @@ -1042,7 +1047,6 @@ dict_create_table_step(
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */

err = dict_build_table_def_step(thr, node);

if (err != DB_SUCCESS) {

goto function_exit;
Expand Down
10 changes: 7 additions & 3 deletions storage/innobase/fil/fil0fil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,9 @@ fil_op_log_parse_or_replay(
if (fil_create_new_single_table_tablespace(
space_id, name, path, flags,
DICT_TF2_USE_TABLESPACE,
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
FIL_IBD_FILE_INITIAL_SIZE,
FIL_SPACE_ENCRYPTION_DEFAULT,
FIL_DEFAULT_ENCRYPTION_KEY) != DB_SUCCESS) {
ut_error;
}
}
Expand Down Expand Up @@ -3331,9 +3333,11 @@ fil_create_new_single_table_tablespace(
const char* dir_path, /*!< in: NULL or a dir path */
ulint flags, /*!< in: tablespace flags */
ulint flags2, /*!< in: table flags2 */
ulint size) /*!< in: the initial size of the
ulint size, /*!< in: the initial size of the
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
os_file_t file;
ibool ret;
Expand Down Expand Up @@ -3500,7 +3504,7 @@ fil_create_new_single_table_tablespace(
}

success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE,
fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY));
fil_space_create_crypt_data(mode, key_id));

if (!success || !fil_node_create(path, size, space_id, FALSE)) {
err = DB_ERROR;
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/fts/fts0fts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1981,7 +1981,7 @@ fts_create_one_index_table(
dict_mem_table_add_col(new_table, heap, "ilist", DATA_BLOB,
4130048, 0);

error = row_create_table_for_mysql(new_table, trx, false);
error = row_create_table_for_mysql(new_table, trx, false, FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);

if (error != DB_SUCCESS) {
trx->error_state = error;
Expand Down
50 changes: 5 additions & 45 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10319,7 +10319,9 @@ create_table_def(
is a zero length-string */
const char* remote_path, /*!< in: Remote path or zero length-string */
ulint flags, /*!< in: table flags */
ulint flags2) /*!< in: table flags2 */
ulint flags2, /*!< in: table flags2 */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
THD* thd = trx->mysql_thd;
dict_table_t* table;
Expand Down Expand Up @@ -10499,7 +10501,7 @@ create_table_def(
fts_add_doc_id_column(table, heap);
}

err = row_create_table_for_mysql(table, trx, false);
err = row_create_table_for_mysql(table, trx, false, mode, key_id);

mem_heap_free(heap);

Expand Down Expand Up @@ -11575,7 +11577,7 @@ ha_innobase::create(
row_mysql_lock_data_dictionary(trx);

error = create_table_def(trx, form, norm_name, temp_path,
remote_path, flags, flags2);
remote_path, flags, flags2, encrypt, key_id);
if (error) {
goto cleanup;
}
Expand Down Expand Up @@ -11735,48 +11737,6 @@ ha_innobase::create(

DBUG_ASSERT(innobase_table != 0);

/* If user has requested that table should be encrypted or table
should remain as unencrypted store crypt data */
if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT) {
ulint maxsize=0;
ulint zip_size = fil_space_get_zip_size(innobase_table->space);
fil_space_crypt_t* old_crypt_data = fil_space_get_crypt_data(innobase_table->space);
fil_space_crypt_t* crypt_data;

crypt_data = fil_space_create_crypt_data(encrypt, key_id);
crypt_data->page0_offset = fsp_header_get_crypt_offset(zip_size, &maxsize);
crypt_data->encryption = encrypt;

/* If there is old crypt data, copy IV */
if (old_crypt_data) {
memcpy(crypt_data->iv, old_crypt_data->iv, sizeof(crypt_data->iv));
}

mtr_t mtr;
mtr_start(&mtr);
/* Get page 0*/
ulint offset = 0;
buf_block_t* block = buf_page_get_gen(innobase_table->space,
zip_size,
offset,
RW_X_LATCH,
NULL,
BUF_GET,
__FILE__, __LINE__,
&mtr);

/* Set up new crypt data */
crypt_data = fil_space_set_crypt_data(innobase_table->space, crypt_data);

/* Compute location to store crypt data */
byte* frame = buf_block_get_frame(block);

/* Write crypt data to page 0 */
fil_space_write_crypt_data(innobase_table->space, frame, crypt_data->page0_offset, maxsize, &mtr);

mtr_commit(&mtr);
}

innobase_copy_frm_flags_from_create_info(innobase_table, create_info);

dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE);
Expand Down
12 changes: 11 additions & 1 deletion storage/innobase/handler/handler0alter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2791,13 +2791,23 @@ prepare_inplace_alter_table_dict(
to rebuild the table with a temporary name. */

if (new_clustered) {
fil_space_crypt_t* crypt_data;
const char* new_table_name
= dict_mem_create_temporary_tablename(
ctx->heap,
ctx->new_table->name,
ctx->new_table->id);
ulint n_cols;
dtuple_t* add_cols;
ulint key_id = FIL_DEFAULT_ENCRYPTION_KEY;
fil_encryption_t mode = FIL_SPACE_ENCRYPTION_DEFAULT;

crypt_data = fil_space_get_crypt_data(ctx->prebuilt->table->space);

if (crypt_data) {
key_id = crypt_data->key_id;
mode = crypt_data->encryption;
}

if (innobase_check_foreigns(
ha_alter_info, altered_table, old_table,
Expand Down Expand Up @@ -2929,7 +2939,7 @@ prepare_inplace_alter_table_dict(
}

error = row_create_table_for_mysql(
ctx->new_table, ctx->trx, false);
ctx->new_table, ctx->trx, false, mode, key_id);

switch (error) {
dict_table_t* temp_table;
Expand Down
7 changes: 6 additions & 1 deletion storage/innobase/include/dict0crea.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Created 1/8/1996 Heikki Tuuri
#include "que0types.h"
#include "row0types.h"
#include "mtr0mtr.h"
#include "fil0crypt.h"

/*********************************************************************//**
Creates a table create graph.
Expand All @@ -43,8 +44,10 @@ tab_create_graph_create(
dict_table_t* table, /*!< in: table to create, built as a memory data
structure */
mem_heap_t* heap, /*!< in: heap where created */
bool commit);/*!< in: true if the commit node should be
bool commit, /*!< in: true if the commit node should be
added to the query graph */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id);/*!< in: encryption key_id */
/*********************************************************************//**
Creates an index create graph.
@return own: index create node */
Expand Down Expand Up @@ -197,6 +200,8 @@ struct tab_node_t{
/* Local storage for this graph node */
ulint state; /*!< node execution state */
ulint col_no; /*!< next column definition to insert */
ulint key_id; /*!< encryption key_id */
fil_encryption_t mode; /*!< encryption mode */
mem_heap_t* heap; /*!< memory heap used as auxiliary storage */
};

Expand Down
23 changes: 13 additions & 10 deletions storage/innobase/include/fil0crypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,20 @@ struct key_struct

struct fil_space_rotate_state_t
{
time_t start_time; // time when rotation started
ulint active_threads; // active threads in space
ulint next_offset; // next "free" offset
ulint max_offset; // max offset needing to be rotated
uint min_key_version_found; // min key version found but not rotated
lsn_t end_lsn; // max lsn created when rotating this space
bool starting; // initial write of IV
bool flushing; // space is being flushed at end of rotate
time_t start_time; /*!< time when rotation started */
ulint active_threads; /*!< active threads in space */
ulint next_offset; /*!< next "free" offset */
ulint max_offset; /*!< max offset needing to be rotated */
uint min_key_version_found; /*!< min key version found but not
rotated */
lsn_t end_lsn; /*!< max lsn created when rotating this
space */
bool starting; /*!< initial write of IV */
bool flushing; /*!< space is being flushed at end of rotate */
struct {
bool is_active; // is scrubbing active in this space
time_t last_scrub_completed; // when was last scrub completed
bool is_active; /*!< is scrubbing active in this space */
time_t last_scrub_completed; /*!< when was last scrub
completed */
} scrubbing;
};

Expand Down
7 changes: 6 additions & 1 deletion storage/innobase/include/fil0fil.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,9 @@ char*
fil_read_link_file(
/*===============*/
const char* name); /*!< in: tablespace name */

#include "fil0crypt.h"

/*******************************************************************//**
Creates a new single-table tablespace to a database directory of MySQL.
Database directories are under the 'datadir' of MySQL. The datadir is the
Expand All @@ -792,9 +795,11 @@ fil_create_new_single_table_tablespace(
const char* dir_path, /*!< in: NULL or a dir path */
ulint flags, /*!< in: tablespace flags */
ulint flags2, /*!< in: table flags2 */
ulint size) /*!< in: the initial size of the
ulint size, /*!< in: the initial size of the
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
__attribute__((nonnull, warn_unused_result));
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Expand Down
5 changes: 4 additions & 1 deletion storage/innobase/include/row0mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Created 9/17/2000 Heikki Tuuri
#include "row0types.h"
#include "btr0pcur.h"
#include "trx0types.h"
#include "fil0crypt.h"

// Forward declaration
struct SysIndexCallback;
Expand Down Expand Up @@ -386,7 +387,9 @@ row_create_table_for_mysql(
(will be freed, or on DB_SUCCESS
added to the data dictionary cache) */
trx_t* trx, /*!< in/out: transaction */
bool commit) /*!< in: if true, commit the transaction */
bool commit, /*!< in: if true, commit the transaction */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
__attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Does an index creation operation for MySQL. TODO: currently failure
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/pars/pars0pars.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2019,7 +2019,8 @@ pars_create_table(
column = static_cast<sym_node_t*>(que_node_get_next(column));
}

node = tab_create_graph_create(table, pars_sym_tab_global->heap, true);
node = tab_create_graph_create(table, pars_sym_tab_global->heap, true,
FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);

table_sym->resolved = TRUE;
table_sym->token_type = SYM_TABLE;
Expand Down
18 changes: 15 additions & 3 deletions storage/innobase/row/row0mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2211,7 +2211,9 @@ row_create_table_for_mysql(
(will be freed, or on DB_SUCCESS
added to the data dictionary cache) */
trx_t* trx, /*!< in/out: transaction */
bool commit) /*!< in: if true, commit the transaction */
bool commit, /*!< in: if true, commit the transaction */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
tab_node_t* node;
mem_heap_t* heap;
Expand Down Expand Up @@ -2324,7 +2326,7 @@ row_create_table_for_mysql(
ut_ad(strstr(table->name, "/FTS_") != NULL);
}

node = tab_create_graph_create(table, heap, commit);
node = tab_create_graph_create(table, heap, commit, mode, key_id);

thr = pars_complete_graph_for_exec(node, trx, heap);

Expand Down Expand Up @@ -3461,10 +3463,19 @@ row_truncate_table_for_mysql(

if (table->space && !DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
/* Discard and create the single-table tablespace. */
fil_space_crypt_t* crypt_data;
ulint space = table->space;
ulint flags = fil_space_get_flags(space);
ulint key_id = FIL_DEFAULT_ENCRYPTION_KEY;
fil_encryption_t mode = FIL_SPACE_ENCRYPTION_DEFAULT;

dict_get_and_save_data_dir_path(table, true);
crypt_data = fil_space_get_crypt_data(space);

if (crypt_data) {
key_id = crypt_data->key_id;
mode = crypt_data->encryption;
}

if (flags != ULINT_UNDEFINED
&& fil_discard_tablespace(space) == DB_SUCCESS) {
Expand All @@ -3483,7 +3494,8 @@ row_truncate_table_for_mysql(
space, table->name,
table->data_dir_path,
flags, table->flags2,
FIL_IBD_FILE_INITIAL_SIZE)
FIL_IBD_FILE_INITIAL_SIZE,
mode, key_id)
!= DB_SUCCESS) {
dict_table_x_unlock_indexes(table);

Expand Down
10 changes: 7 additions & 3 deletions storage/xtradb/dict/dict0crea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ dict_build_table_def_step(
space, table->name, path,
dict_tf_to_fsp_flags(table->flags),
table->flags2,
FIL_IBD_FILE_INITIAL_SIZE);
FIL_IBD_FILE_INITIAL_SIZE,
node->mode, node->key_id);

table->space = (unsigned int) space;

Expand Down Expand Up @@ -934,8 +935,10 @@ tab_create_graph_create(
dict_table_t* table, /*!< in: table to create, built as a memory data
structure */
mem_heap_t* heap, /*!< in: heap where created */
bool commit) /*!< in: true if the commit node should be
bool commit, /*!< in: true if the commit node should be
added to the query graph */
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
tab_node_t* node;

Expand All @@ -948,6 +951,8 @@ tab_create_graph_create(

node->state = TABLE_BUILD_TABLE_DEF;
node->heap = mem_heap_create(256);
node->mode = mode;
node->key_id = key_id;

node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
heap);
Expand Down Expand Up @@ -1042,7 +1047,6 @@ dict_create_table_step(
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */

err = dict_build_table_def_step(thr, node);

if (err != DB_SUCCESS) {

goto function_exit;
Expand Down
Loading

0 comments on commit bfb6ea0

Please sign in to comment.