mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-38246 aria_read index failed on encrypted database during backup
The backup of encrypted Aria tables was not supported. Added support for this. One complication is that the page checksum is for the not encrypted page. To be able to verify the checksum I have to temporarly decrypt the page. In the backup we store the encrypted pages. Other things: - Fixed some (not critical) memory leaks in mariabackup
This commit is contained in:
@@ -161,7 +161,10 @@ public:
|
||||
File m_data_file = -1;
|
||||
MY_STAT m_data_file_stat;
|
||||
};
|
||||
Table() = default;
|
||||
Table()
|
||||
{
|
||||
bzero(&m_cap, sizeof(m_cap));
|
||||
}
|
||||
Table (Table &&other) = delete;
|
||||
Table & operator= (Table &&other) = delete;
|
||||
Table(const Table &) = delete;
|
||||
@@ -222,6 +225,7 @@ private:
|
||||
};
|
||||
|
||||
Table::~Table() {
|
||||
aria_free_capabilities(&m_cap);
|
||||
(void)close();
|
||||
}
|
||||
|
||||
@@ -298,7 +302,8 @@ bool Table::open(MYSQL *con, bool opt_no_lock, unsigned thread_num) {
|
||||
goto exit;
|
||||
}
|
||||
if (!have_capabilities) {
|
||||
if ((error= aria_get_capabilities(partition.m_index_file, &m_cap))) {
|
||||
if ((error= aria_get_capabilities(partition.m_index_file,
|
||||
m_full_name.c_str(), &m_cap))) {
|
||||
msg(thread_num, "aria_get_capabilities failed: %d", error);
|
||||
goto exit;
|
||||
}
|
||||
@@ -343,6 +348,7 @@ exit:
|
||||
}
|
||||
|
||||
bool Table::close() {
|
||||
aria_free_capabilities(&m_cap);
|
||||
for (Partition &partition : m_partitions) {
|
||||
if (partition.m_index_file >= 0) {
|
||||
my_close(partition.m_index_file, MYF(MY_WME));
|
||||
@@ -409,14 +415,17 @@ bool Table::copy(ds_ctxt_t *ds, bool is_index, unsigned thread_num) {
|
||||
{
|
||||
if (error == HA_ERR_END_OF_FILE)
|
||||
break;
|
||||
msg(thread_num, "error: aria_read %s failed: %d",
|
||||
is_index ? "index" : "data", error);
|
||||
msg(thread_num, "error: aria_read %s from %s failed "
|
||||
"with error %d",
|
||||
is_index ? "index" : "data", full_name.c_str(),
|
||||
error);
|
||||
goto err;
|
||||
}
|
||||
xtrabackup_io_throttling();
|
||||
if ((error = ds_write(dst_file, copy_buffer, length))) {
|
||||
msg(thread_num, "error: aria_write failed: %d", error);
|
||||
goto err;
|
||||
msg(thread_num, "error: aria_write to %s failed "
|
||||
"with error: %d", dst_path, error);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -546,6 +546,7 @@ bool get_mysql_vars(MYSQL *connection)
|
||||
xb_load_list_string(ignore_db_dirs, ",", register_ignore_db_dirs_filter);
|
||||
|
||||
out:
|
||||
free_mysql_variables(mysql_vars);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -1513,7 +1514,9 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
domain_id ? domain_id : domain_id55);
|
||||
|
||||
cleanup:
|
||||
free_mysql_variables(vars);
|
||||
free_mysql_variables(status);
|
||||
free_mysql_variables(value);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
extern struct st_maria_plugin *mysql_optional_plugins[];
|
||||
extern struct st_maria_plugin *mysql_mandatory_plugins[];
|
||||
static void encryption_plugin_init(int argc, char **argv);
|
||||
void initialize_default_encryption();
|
||||
|
||||
extern char *xb_plugin_load;
|
||||
extern char *xb_plugin_dir;
|
||||
@@ -140,7 +141,10 @@ void encryption_plugin_backup_init(MYSQL *mysql)
|
||||
}
|
||||
mysql_free_result(result);
|
||||
if (!plugin_load.length())
|
||||
{
|
||||
initialize_default_encryption();
|
||||
return;
|
||||
}
|
||||
|
||||
oss << "plugin_load=" << plugin_load.c_str() + 1 << std::endl;
|
||||
|
||||
@@ -248,3 +252,45 @@ static void encryption_plugin_init(int argc, char **argv)
|
||||
plugin_init(&argc, argv, PLUGIN_INIT_SKIP_PLUGIN_TABLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Setup encryption_handler with default encryption to avoid crashes when
|
||||
calling encryption_get_key
|
||||
*/
|
||||
uint no_get_key(uint, uint, uchar*, uint*)
|
||||
{
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
}
|
||||
uint no_key(uint)
|
||||
{
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
}
|
||||
|
||||
static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen, int flags,
|
||||
unsigned int key_id, unsigned int key_version)
|
||||
{
|
||||
return my_aes_crypt_init(ctx, MY_AES_CBC, flags, key, klen, iv, ivlen);
|
||||
}
|
||||
|
||||
static unsigned int get_length(unsigned int slen, unsigned int key_id,
|
||||
unsigned int key_version)
|
||||
{
|
||||
return my_aes_get_size(MY_AES_CBC, slen);
|
||||
}
|
||||
|
||||
uint ctx_size(unsigned int, unsigned int)
|
||||
{
|
||||
return MY_AES_CTX_SIZE;
|
||||
}
|
||||
|
||||
void initialize_default_encryption()
|
||||
{
|
||||
encryption_handler.encryption_ctx_size_func= ctx_size;
|
||||
encryption_handler.encryption_ctx_init_func= ctx_init;
|
||||
encryption_handler.encryption_ctx_update_func= my_aes_crypt_update;
|
||||
encryption_handler.encryption_ctx_finish_func= my_aes_crypt_finish;
|
||||
encryption_handler.encryption_encrypted_length_func= get_length;
|
||||
encryption_handler.encryption_key_get_func= no_get_key;
|
||||
encryption_handler.encryption_key_get_latest_version_func= no_key;
|
||||
}
|
||||
|
||||
@@ -5486,6 +5486,7 @@ fail:
|
||||
if (fil_system.is_initialised()) {
|
||||
innodb_shutdown();
|
||||
}
|
||||
backup_datasinks.destroy();
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,15 @@
|
||||
|
||||
/* Interfaces for doing backups of Aria tables */
|
||||
|
||||
#ifndef ARIA_BACKUP_INCLUDED
|
||||
|
||||
C_MODE_START
|
||||
|
||||
typedef struct st_aria_table_capabilities
|
||||
{
|
||||
my_off_t header_size;
|
||||
MARIA_CRYPT_DATA *crypt_data;
|
||||
uint crypt_page_header_space;
|
||||
ulong bitmap_pages_covered;
|
||||
uint block_size;
|
||||
uint keypage_header;
|
||||
@@ -32,11 +36,15 @@ typedef struct st_aria_table_capabilities
|
||||
/* s3 capabilities */
|
||||
ulong s3_block_size;
|
||||
uint8 compression;
|
||||
char filename[FN_REFLEN];
|
||||
} ARIA_TABLE_CAPABILITIES;
|
||||
|
||||
int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap);
|
||||
int aria_get_capabilities(File kfile, const char *table_name, ARIA_TABLE_CAPABILITIES *cap);
|
||||
void aria_free_capabilities(ARIA_TABLE_CAPABILITIES *cap);
|
||||
int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
uchar *buffer);
|
||||
int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
uchar *buffer, size_t *bytes_read);
|
||||
C_MODE_END
|
||||
|
||||
#endif /* ARIA_BACKUP_INCLUDED */
|
||||
|
||||
7
mysql-test/suite/mariabackup/aria_encrypted.opt
Normal file
7
mysql-test/suite/mariabackup/aria_encrypted.opt
Normal file
@@ -0,0 +1,7 @@
|
||||
--loose-innodb-encrypt-log=ON
|
||||
--plugin-load-add=$FILE_KEY_MANAGEMENT_SO
|
||||
--loose-file-key-management
|
||||
--loose-file-key-management-filekey=FILE:$MTR_SUITE_DIR/filekeys-data.key
|
||||
--loose-file-key-management-filename=$MTR_SUITE_DIR/filekeys-data.enc
|
||||
--loose-file-key-management-encryption-algorithm=aes_cbc
|
||||
--aria-encrypt-tables=ON
|
||||
8
mysql-test/suite/mariabackup/aria_encrypted.result
Normal file
8
mysql-test/suite/mariabackup/aria_encrypted.result
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# MDEV-38246 aria_read index failed on encrypted database during backup
|
||||
#
|
||||
CREATE TABLE t1 (product_id varchar(32) DEFAULT NULL, d1 date DEFAULT NULL, key(product_id)) engine=aria, row_format=page, transactional=1;
|
||||
CREATE TABLE t2 (product_id varchar(32) DEFAULT NULL, d1 date DEFAULT NULL, key(product_id)) engine=aria, row_format=page, transactional=0;
|
||||
insert into t1 select md5(seq), date_add("2025-05-05", interval seq day) from seq_1_to_10000;
|
||||
insert into t2 select md5(seq), date_add("2025-05-05", interval seq day) from seq_1_to_10000;
|
||||
drop table if exists t1,t2;
|
||||
18
mysql-test/suite/mariabackup/aria_encrypted.test
Normal file
18
mysql-test/suite/mariabackup/aria_encrypted.test
Normal file
@@ -0,0 +1,18 @@
|
||||
--source include/have_file_key_management.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_sequence.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-38246 aria_read index failed on encrypted database during backup
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (product_id varchar(32) DEFAULT NULL, d1 date DEFAULT NULL, key(product_id)) engine=aria, row_format=page, transactional=1;
|
||||
CREATE TABLE t2 (product_id varchar(32) DEFAULT NULL, d1 date DEFAULT NULL, key(product_id)) engine=aria, row_format=page, transactional=0;
|
||||
|
||||
insert into t1 select md5(seq), date_add("2025-05-05", interval seq day) from seq_1_to_10000;
|
||||
insert into t2 select md5(seq), date_add("2025-05-05", interval seq day) from seq_1_to_10000;
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
drop table if exists t1,t2;
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "maria_def.h"
|
||||
#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */
|
||||
#include "ma_checkpoint.h"
|
||||
#include "ma_crypt.h"
|
||||
#include <aria_backup.h>
|
||||
|
||||
/**
|
||||
@@ -30,8 +31,11 @@
|
||||
@return X errno
|
||||
*/
|
||||
|
||||
int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)__attribute__((visibility("default"))) ;
|
||||
int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
|
||||
int aria_get_capabilities(File kfile, const char *table_name,
|
||||
ARIA_TABLE_CAPABILITIES *cap)
|
||||
__attribute__((visibility("default"))) ;
|
||||
int aria_get_capabilities(File kfile, const char *table_name,
|
||||
ARIA_TABLE_CAPABILITIES *cap)
|
||||
{
|
||||
MARIA_SHARE share;
|
||||
int error= 0;
|
||||
@@ -42,6 +46,7 @@ int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
|
||||
DBUG_ENTER("aria_get_capabilities");
|
||||
|
||||
bzero(cap, sizeof(*cap));
|
||||
bzero(&share, sizeof(share));
|
||||
if (my_pread(kfile,share.state.header.file_version, head_length, 0,
|
||||
MYF(MY_NABP)))
|
||||
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
|
||||
@@ -67,13 +72,14 @@ int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
|
||||
goto err;
|
||||
}
|
||||
_ma_base_info_read(disc_cache + base_pos, &share.base);
|
||||
strmake(cap->filename, table_name, sizeof(cap->filename)-1);
|
||||
cap->transactional= share.base.born_transactional;
|
||||
cap->checksum= MY_TEST(share.options & HA_OPTION_PAGE_CHECKSUM);
|
||||
cap->online_backup_safe= cap->transactional && cap->checksum;
|
||||
cap->header_size= share.base.keystart;
|
||||
cap->keypage_header= ((share.base.born_transactional ?
|
||||
LSN_STORE_SIZE + TRANSID_SIZE :
|
||||
0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE +
|
||||
LSN_STORE_SIZE + TRANSID_SIZE : 0) +
|
||||
KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE +
|
||||
KEYPAGE_USED_SIZE);
|
||||
cap->block_size= share.base.block_size;
|
||||
cap->data_file_type= share.state.header.data_file_type;
|
||||
@@ -81,10 +87,23 @@ int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
|
||||
cap->compression= share.base.compression_algorithm;
|
||||
cap->encrypted= MY_TEST(share.base.extra_options &
|
||||
MA_EXTRA_OPTIONS_ENCRYPTED);
|
||||
if (cap->encrypted)
|
||||
{
|
||||
share.data_file_name.str= (char*) table_name; /* in case of error */
|
||||
share.crypt_data= 0;
|
||||
if (maria_read_crypt_data(kfile, &share))
|
||||
{
|
||||
error= HA_ERR_DECRYPTION_FAILED;
|
||||
goto err;
|
||||
}
|
||||
cap->keypage_header+= ma_crypt_get_index_page_header_space(&share);
|
||||
cap->crypt_data= share.crypt_data;
|
||||
cap->crypt_page_header_space= ma_crypt_get_data_page_header_space();
|
||||
}
|
||||
|
||||
if (share.state.header.data_file_type == BLOCK_RECORD)
|
||||
{
|
||||
/* Calulate how man pages the row bitmap covers. From _ma_bitmap_init() */
|
||||
/* Calulate how many pages the row bitmap covers. From _ma_bitmap_init() */
|
||||
aligned_bit_blocks= (cap->block_size - PAGE_SUFFIX_SIZE) / 6;
|
||||
/*
|
||||
In each 6 bytes, we have 6*8/3 = 16 pages covered
|
||||
@@ -100,9 +119,26 @@ int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
|
||||
|
||||
err:
|
||||
my_free(disc_cache);
|
||||
if (error)
|
||||
aria_free_capabilities(cap);
|
||||
DBUG_RETURN(error);
|
||||
} /* aria_get_capabilities */
|
||||
|
||||
|
||||
void aria_free_capabilities(ARIA_TABLE_CAPABILITIES *cap)
|
||||
{
|
||||
DBUG_ENTER("aria_free_capabilities");
|
||||
if (cap->crypt_data)
|
||||
{
|
||||
MARIA_SHARE share;
|
||||
share.crypt_data= cap->crypt_data;
|
||||
ma_crypt_free(&share);
|
||||
cap->crypt_data= 0;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** store MARIA_BASE_INFO
|
||||
****************************************************************************/
|
||||
@@ -171,14 +207,14 @@ int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
uchar *buffer)
|
||||
{
|
||||
MARIA_SHARE share;
|
||||
int retry= 0;
|
||||
int retry= 0, error= 0;
|
||||
DBUG_ENTER("aria_read_index");
|
||||
|
||||
share.keypage_header= cap->keypage_header;
|
||||
share.block_size= cap->block_size;
|
||||
do
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int error;
|
||||
size_t length;
|
||||
if ((length= my_pread(kfile, buffer, cap->block_size,
|
||||
block * cap->block_size, MYF(0))) != cap->block_size)
|
||||
@@ -199,15 +235,53 @@ int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
length= _ma_get_page_used(&share, buffer);
|
||||
if (length > cap->block_size - CRC_SIZE)
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
|
||||
if (cap->encrypted)
|
||||
{
|
||||
/* We have to decrypt block to be able to calculate checksum */
|
||||
PAGECACHE_IO_HOOK_ARGS io_arg;
|
||||
my_bool crypt_error;
|
||||
io_arg.data= (void*) &share;
|
||||
io_arg.page= buffer;
|
||||
io_arg.crypt_buf= (uchar*) my_alloca(cap->block_size);
|
||||
io_arg.pageno= block;
|
||||
share.crypt_data= cap->crypt_data;
|
||||
share.silence_encryption_errors= 1;
|
||||
share.crypt_page_header_space= cap->crypt_page_header_space;
|
||||
share.open_file_name.str= cap->filename;
|
||||
|
||||
crypt_error= ma_crypt_index_post_read_hook(0, &io_arg);
|
||||
my_afree(io_arg.crypt_buf);
|
||||
if (!crypt_error)
|
||||
DBUG_RETURN(0); /* ok */
|
||||
error= my_errno;
|
||||
if (error == HA_ERR_DECRYPTION_FAILED ||
|
||||
error == HA_ERR_WRONG_CRC)
|
||||
goto retry;
|
||||
break; /* Give error */
|
||||
}
|
||||
|
||||
error= maria_page_crc_check(buffer, block, &share,
|
||||
MARIA_NO_CRC_NORMAL_PAGE,
|
||||
(int) length);
|
||||
if (error == 0 || my_errno != HA_ERR_WRONG_CRC)
|
||||
DBUG_RETURN(error);
|
||||
if (error == 0)
|
||||
DBUG_RETURN(0);
|
||||
if ((error= my_errno) != HA_ERR_WRONG_CRC)
|
||||
break;
|
||||
}
|
||||
retry:
|
||||
if (retry++ >= MAX_RETRY)
|
||||
{
|
||||
error= HA_ERR_WRONG_CRC;
|
||||
break;
|
||||
}
|
||||
my_sleep(100000); /* Sleep 0.1 seconds */
|
||||
} while (retry++ < MAX_RETRY);
|
||||
DBUG_RETURN(HA_ERR_WRONG_CRC);
|
||||
}
|
||||
my_printf_error(error,
|
||||
"Error %d reading index file %s block %lld",
|
||||
MYF(ME_FATAL|ME_ERROR_LOG),
|
||||
error, cap->filename, block);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +303,7 @@ int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
uchar *buffer, size_t *bytes_read)
|
||||
{
|
||||
MARIA_SHARE share;
|
||||
int retry= 0;
|
||||
int retry= 0, error= 0;
|
||||
DBUG_ENTER("aria_read_data");
|
||||
|
||||
share.keypage_header= cap->keypage_header;
|
||||
@@ -243,11 +317,9 @@ int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
||||
DBUG_RETURN(*bytes_read > 0 ? 0 : (my_errno ? my_errno : -1));
|
||||
}
|
||||
|
||||
*bytes_read= cap->block_size;
|
||||
do
|
||||
for (;;)
|
||||
{
|
||||
int error;
|
||||
size_t length;
|
||||
if ((length= my_pread(dfile, buffer, cap->block_size,
|
||||
block * cap->block_size, MYF(0))) != cap->block_size)
|
||||
@@ -265,17 +337,55 @@ int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
|
||||
if (length == cap->block_size)
|
||||
{
|
||||
if (!_ma_check_if_zero(buffer, share.block_size - CRC_SIZE))
|
||||
error= 0;
|
||||
DBUG_RETURN(0);
|
||||
/* Test if encrypted pages. Note that bitmap pages are not encrypted */
|
||||
if (cap->encrypted && (block % cap->bitmap_pages_covered))
|
||||
{
|
||||
/* We have to decrypt block to be able to calculate checksum */
|
||||
PAGECACHE_IO_HOOK_ARGS io_arg;
|
||||
my_bool crypt_error;
|
||||
io_arg.data= (void*) &share;
|
||||
io_arg.page= buffer;
|
||||
io_arg.crypt_buf= (uchar*) my_alloca(cap->block_size);
|
||||
io_arg.pageno= block;
|
||||
share.crypt_data= cap->crypt_data;
|
||||
share.silence_encryption_errors= 1;
|
||||
share.crypt_page_header_space= cap->crypt_page_header_space;
|
||||
share.open_file_name.str= cap->filename;
|
||||
|
||||
crypt_error= ma_crypt_data_post_read_hook(0, &io_arg);
|
||||
my_afree(io_arg.crypt_buf);
|
||||
if (!crypt_error)
|
||||
DBUG_RETURN(0); /* ok */
|
||||
if (my_errno == HA_ERR_DECRYPTION_FAILED || my_errno== HA_ERR_WRONG_CRC)
|
||||
goto retry;
|
||||
error= my_errno;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
error= maria_page_crc_check(buffer, block, &share,
|
||||
((block % cap->bitmap_pages_covered) == 0 ?
|
||||
MARIA_NO_CRC_BITMAP_PAGE :
|
||||
MARIA_NO_CRC_NORMAL_PAGE),
|
||||
share.block_size - CRC_SIZE);
|
||||
if (error == 0 || my_errno != HA_ERR_WRONG_CRC)
|
||||
DBUG_RETURN(error);
|
||||
((block % cap->bitmap_pages_covered) == 0 ?
|
||||
MARIA_NO_CRC_BITMAP_PAGE :
|
||||
MARIA_NO_CRC_NORMAL_PAGE),
|
||||
share.block_size - CRC_SIZE);
|
||||
if (error == 0)
|
||||
DBUG_RETURN(0);
|
||||
if ((error= my_errno) != HA_ERR_WRONG_CRC)
|
||||
break;
|
||||
}
|
||||
}
|
||||
retry:
|
||||
if (retry++ >= MAX_RETRY)
|
||||
{
|
||||
error= HA_ERR_WRONG_CRC;
|
||||
break;
|
||||
}
|
||||
my_sleep(100000); /* Sleep 0.1 seconds */
|
||||
} while (retry++ < MAX_RETRY);
|
||||
DBUG_RETURN(HA_ERR_WRONG_CRC);
|
||||
}
|
||||
my_printf_error(error,
|
||||
"Error %d reading data file %s block %lld",
|
||||
MYF(ME_FATAL|ME_ERROR_LOG),
|
||||
error, cap->filename, block);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,9 @@ struct st_crypt_key
|
||||
struct st_maria_crypt_data
|
||||
{
|
||||
struct st_encryption_scheme scheme;
|
||||
uint space;
|
||||
mysql_mutex_t lock; /* protecting keys */
|
||||
uint space;
|
||||
my_bool no_alloc;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -105,6 +106,7 @@ ma_crypt_create(MARIA_SHARE* share)
|
||||
(MARIA_CRYPT_DATA*)my_malloc(PSI_INSTRUMENT_ME, sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL));
|
||||
crypt_data->scheme.type= CRYPT_SCHEME_1;
|
||||
crypt_data->scheme.locker= crypt_data_scheme_locker;
|
||||
crypt_data->no_alloc= 0;
|
||||
mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock, MY_MUTEX_INIT_FAST);
|
||||
crypt_data->scheme.key_id= get_encryption_key_id(share);
|
||||
my_random_bytes(crypt_data->scheme.iv, sizeof(crypt_data->scheme.iv));
|
||||
@@ -156,7 +158,7 @@ ma_crypt_write(MARIA_SHARE* share, File file)
|
||||
}
|
||||
|
||||
uchar*
|
||||
ma_crypt_read(MARIA_SHARE* share, uchar *buff, my_bool silent)
|
||||
ma_crypt_read(MARIA_SHARE* share, uchar *buff, my_bool silent, my_bool no_alloc)
|
||||
{
|
||||
uchar type= buff[0];
|
||||
uchar iv_length= buff[1];
|
||||
@@ -176,7 +178,8 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff, my_bool silent)
|
||||
{
|
||||
/* opening a table */
|
||||
MARIA_CRYPT_DATA *crypt_data=
|
||||
(MARIA_CRYPT_DATA*)my_malloc(PSI_INSTRUMENT_ME, sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL));
|
||||
(MARIA_CRYPT_DATA*) my_malloc(PSI_INSTRUMENT_ME,
|
||||
sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL));
|
||||
uint key_version;
|
||||
|
||||
crypt_data->scheme.type= type;
|
||||
@@ -185,6 +188,7 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff, my_bool silent)
|
||||
crypt_data->scheme.locker= crypt_data_scheme_locker;
|
||||
crypt_data->scheme.key_id= get_encryption_key_id(share);
|
||||
crypt_data->space= uint4korr(buff + 2);
|
||||
crypt_data->no_alloc= no_alloc;
|
||||
memcpy(crypt_data->scheme.iv, buff + 6, sizeof(crypt_data->scheme.iv));
|
||||
share->crypt_data= crypt_data;
|
||||
|
||||
@@ -226,8 +230,8 @@ static my_bool ma_crypt_pre_read_hook(PAGECACHE_IO_HOOK_ARGS *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static my_bool ma_crypt_data_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args)
|
||||
my_bool ma_crypt_data_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args)
|
||||
{
|
||||
MARIA_SHARE *share= (MARIA_SHARE*) args->data;
|
||||
const uint size= share->block_size;
|
||||
@@ -263,7 +267,8 @@ static my_bool ma_crypt_data_post_read_hook(int res,
|
||||
uchar *tmp= args->page;
|
||||
args->page= args->crypt_buf;
|
||||
args->crypt_buf= NULL;
|
||||
my_free(tmp);
|
||||
if (!share->crypt_data->no_alloc)
|
||||
my_free(tmp);
|
||||
}
|
||||
|
||||
return maria_page_crc_check_data(res, args);
|
||||
@@ -361,8 +366,8 @@ void ma_crypt_set_data_pagecache_callbacks(PAGECACHE_FILE *file,
|
||||
}
|
||||
}
|
||||
|
||||
static my_bool ma_crypt_index_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args)
|
||||
my_bool ma_crypt_index_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args)
|
||||
{
|
||||
MARIA_SHARE *share= (MARIA_SHARE*) args->data;
|
||||
const uint block_size= share->block_size;
|
||||
@@ -403,7 +408,8 @@ static my_bool ma_crypt_index_post_read_hook(int res,
|
||||
uchar *tmp= args->page;
|
||||
args->page= args->crypt_buf;
|
||||
args->crypt_buf= NULL;
|
||||
my_free(tmp);
|
||||
if (!share->crypt_data->no_alloc)
|
||||
my_free(tmp);
|
||||
}
|
||||
|
||||
return maria_page_crc_check_index(res, args);
|
||||
|
||||
@@ -26,9 +26,12 @@ 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,
|
||||
my_bool silent); /* read crypt data*/
|
||||
|
||||
uchar *ma_crypt_read(struct st_maria_share *, uchar *buff,
|
||||
my_bool silent, my_bool no_alloc); /* read crypt data */
|
||||
my_bool ma_crypt_data_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args);
|
||||
my_bool ma_crypt_index_post_read_hook(int res,
|
||||
PAGECACHE_IO_HOOK_ARGS *args);
|
||||
void ma_crypt_set_data_pagecache_callbacks(struct st_pagecache_file *file,
|
||||
struct st_maria_share *share);
|
||||
|
||||
|
||||
@@ -973,7 +973,7 @@ 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,
|
||||
MY_TEST(open_flags & HA_OPEN_FOR_DROP))))
|
||||
MY_TEST(open_flags & HA_OPEN_FOR_DROP), 0)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1258,6 +1258,52 @@ err:
|
||||
} /* maria_open */
|
||||
|
||||
|
||||
/*
|
||||
Read the crypt from a maria key file
|
||||
Crypt_data stored in share->crypt_data
|
||||
*/
|
||||
|
||||
my_bool maria_read_crypt_data(File kfile, MARIA_SHARE *share)
|
||||
{
|
||||
size_t base_pos, info_length, crypt_length;
|
||||
uchar *cache;
|
||||
uint keys, key_segs, uniques, unique_key_parts, columns;
|
||||
my_bool error;
|
||||
DBUG_ENTER("maria_read_crypt_data");
|
||||
|
||||
DBUG_ASSERT(share->base.extra_options & MA_EXTRA_OPTIONS_ENCRYPTED);
|
||||
keys= (uint) share->state.header.keys;
|
||||
key_segs= mi_uint2korr(share->state.header.key_parts);
|
||||
uniques= (uint) share->state.header.uniques;
|
||||
unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
|
||||
columns= share->base.fields;
|
||||
|
||||
base_pos= mi_uint2korr(share->state.header.base_pos);
|
||||
/* Same calculation as in maria_create() */
|
||||
info_length= base_pos+(uint) (MARIA_BASE_INFO_SIZE+
|
||||
keys * MARIA_KEYDEF_SIZE+
|
||||
uniques * MARIA_UNIQUEDEF_SIZE +
|
||||
(key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
|
||||
columns*(MARIA_COLUMNDEF_SIZE + 2));
|
||||
crypt_length= mi_uint2korr(share->state.header.header_length) - info_length;
|
||||
if ((longlong) crypt_length < 0 || crypt_length > 1024)
|
||||
{
|
||||
my_errno=HA_ERR_NOT_A_TABLE;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
cache= (uchar*) my_alloca(crypt_length);
|
||||
|
||||
error= 0;
|
||||
if (mysql_file_pread(kfile, cache, crypt_length, info_length,
|
||||
MYF(MY_FNABP | MY_WME)) ||
|
||||
!ma_crypt_read(share, cache, 0, 1))
|
||||
error= 1;
|
||||
my_afree(cache);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Reallocate a buffer, if the current buffer is not large enough
|
||||
*/
|
||||
|
||||
@@ -1659,6 +1659,7 @@ int _ma_open_keyfile(MARIA_SHARE *share);
|
||||
void _ma_setup_functions(MARIA_SHARE *share);
|
||||
my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size);
|
||||
void _ma_remap_file(MARIA_HA *info, my_off_t size);
|
||||
my_bool maria_read_crypt_data(File kfile, MARIA_SHARE *share);
|
||||
|
||||
MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info, const uchar *record);
|
||||
my_bool _ma_write_abort_default(MARIA_HA *info);
|
||||
|
||||
@@ -411,7 +411,7 @@ int aria_copy_to_s3(ms3_st *s3_client, const char *aws_bucket,
|
||||
O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
|
||||
MYF(MY_WME))) < 0)
|
||||
DBUG_RETURN(1);
|
||||
if ((error= aria_get_capabilities(file, &cap)))
|
||||
if ((error= aria_get_capabilities(file, table_name, &cap)))
|
||||
{
|
||||
fprintf(stderr, "Got error %d when reading Aria header from %s\n",
|
||||
error, path);
|
||||
|
||||
@@ -103,7 +103,7 @@ static int copy_table(const char *table_name, int stage)
|
||||
O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
|
||||
MYF(MY_WME))) < 0)
|
||||
goto err;
|
||||
if ((error= aria_get_capabilities(org_file, &cap)))
|
||||
if ((error= aria_get_capabilities(org_file, table_name, &cap)))
|
||||
{
|
||||
fprintf(stderr, "aria_get_capabilities failed: %d\n", error);
|
||||
goto err;
|
||||
|
||||
Reference in New Issue
Block a user