Commit a0d396fd authored by Jan Lindström's avatar Jan Lindström

MDEV-11684: post-10.1-merge fixes

10.1 is merged into 10.2 now. Two issues are left to fix:
(1) encryption.innochecksum test
(2) read_page0 vs page_0_crypt_read

(1) innochecksum tool did not compile after merge because
buf_page_is_corrupted uses fil_crypt_t that has been changed.

extra/CMakeLists.txt: Added fil/fil0crypt.cc as dependency
as we need to use fil_crypt_verify_checksum for encrypted pages.

innochecksum.cc: If we think page is encrypted i.e.
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION != 0 we call
fil_crypt_verify_checksum() function to compare calculated
checksum to stored checksum calculated after encryption
(this is stored on different offset i.e.
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4).
If checksum does not match we call normal buf_page_is_corrupted
to compare calculated checksum to stored checksum.

fil0crypt.cc: add #ifdef UNIV_INNOCHECKSUM to be able to compile
this file for innochecksum tool.

(2) read_page0 is not needed and thus removed.
parent 8a04b8ca
......@@ -80,6 +80,7 @@ IF(WITH_INNOBASE_STORAGE_ENGINE OR WITH_XTRADB_STORAGE_ENGINE)
../storage/innobase/buf/buf0buf.cc
../storage/innobase/page/page0zip.cc
../storage/innobase/os/os0file.cc
../storage/innobase/fil/fil0crypt.cc
)
......
/*
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, 2016, MariaDB Corporation.
Copyright (c) 2014, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -70,6 +70,24 @@ The parts not included are excluded by #ifndef UNIV_INNOCHECKSUM. */
#define PRIuMAX "llu"
#endif
/*********************************************************************
Verify checksum for a page (iff it's encrypted)
NOTE: currently this function can only be run in single threaded mode
as it modifies srv_checksum_algorithm (temporarily)
@param[in] src_fame page to verify
@param[in] page_size page_size
@param[in] page_no page number of given read_buf
@param[in] strict_check true if strict-check option is enabled
@return true if page is encrypted AND OK, false otherwise */
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*============================*/
const byte* src_frame, /*!< in: page the verify */
const page_size_t& page_size /*!< in: page size */
,uintmax_t page_no,
bool strict_check);
/* Global variables */
static bool verbose;
static bool just_count;
......@@ -564,9 +582,25 @@ is_page_corrupted(
}
}
is_corrupted = buf_page_is_corrupted(
true, buf, page_size, false, cur_page_num, strict_verify,
is_log_enabled, log_file);
/* If page is encrypted, use different checksum calculation
as innochecksum can't decrypt pages. Note that some old InnoDB
versions did not initialize FIL_PAGE_FILE_FLUSH_LSN field
so if crypt checksum does not match we verify checksum using
normal method.
*/
if (mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0) {
is_corrupted = fil_space_verify_crypt_checksum(buf, page_size,
cur_page_num, strict_verify);
} else {
is_corrupted = true;
}
if (is_corrupted) {
is_corrupted = buf_page_is_corrupted(
true, buf, page_size, false,
cur_page_num, strict_verify,
is_log_enabled, log_file);
}
return(is_corrupted);
}
......
......@@ -13,4 +13,4 @@
innodb_scrub : MDEV-8139
innodb_scrub_compressed : MDEV-8139
innodb_scrub_background : MDEV-8139
innochecksum: see buf_page_is_corrupted()
......@@ -846,7 +846,7 @@ buf_page_is_corrupted(
ulint checksum_field2;
bool page_encrypted = false;
#ifndef UNIV_INNOCHECKSUM // FIXME see also encryption.innochecksum test
#ifndef UNIV_INNOCHECKSUM
ulint space_id = mach_read_from_4(
read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
......@@ -859,6 +859,12 @@ buf_page_is_corrupted(
fil_page_is_encrypted(read_buf)) {
page_encrypted = true;
}
#else
if (mach_read_from_4(read_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0
|| mach_read_from_2(read_buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
page_encrypted = true;
}
#endif
DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
......
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -24,14 +24,16 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
*******************************************************/
#include "fil0fil.h"
#include "mach0data.h"
#include "page0size.h"
#include "page0zip.h"
#ifndef UNIV_INNOCHECKSUM
#include "fil0crypt.h"
#include "srv0srv.h"
#include "srv0start.h"
#include "mach0data.h"
#include "log0recv.h"
#include "mtr0mtr.h"
#include "mtr0log.h"
#include "page0zip.h"
#include "ut0ut.h"
#include "btr0scrub.h"
#include "fsp0fsp.h"
......@@ -910,81 +912,6 @@ fil_crypt_calculate_checksum(
return checksum;
}
/*********************************************************************
Verify checksum for a page (iff it's encrypted)
NOTE: currently this function can only be run in single threaded mode
as it modifies srv_checksum_algorithm (temporarily)
@return true if page is encrypted AND OK, false otherwise */
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*============================*/
const byte* src_frame, /*!< in: page the verify */
const page_size_t& page_size) /*!< in: page size */
{
// key version
uint key_version = mach_read_from_4(
src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
if (key_version == 0) {
return false; // unencrypted page
}
/* "trick" the normal checksum routines by storing the post-encryption
* checksum into the normal checksum field allowing for reuse of
* the normal routines */
// post encryption checksum
ib_uint32_t stored_post_encryption = mach_read_from_4(
src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
// save pre encryption checksum for restore in end of this function
ib_uint32_t stored_pre_encryption = mach_read_from_4(
src_frame + FIL_PAGE_SPACE_OR_CHKSUM);
ib_uint32_t checksum_field2 = mach_read_from_4(
src_frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
/** prepare frame for usage of normal checksum routines */
mach_write_to_4(const_cast<byte*>(src_frame) + FIL_PAGE_SPACE_OR_CHKSUM,
stored_post_encryption);
/* NOTE: this function is (currently) only run when restoring
* dblwr-buffer, server is single threaded so it's safe to modify
* srv_checksum_algorithm */
srv_checksum_algorithm_t save_checksum_algorithm =
(srv_checksum_algorithm_t)srv_checksum_algorithm;
if (!page_size.is_compressed() &&
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
/* handle ALGORITHM_INNODB specially,
* "downgrade" to ALGORITHM_INNODB and store BUF_NO_CHECKSUM_MAGIC
* checksum_field2 is sort of pointless anyway...
*/
srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB;
mach_write_to_4(const_cast<byte*>(src_frame) +
UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
BUF_NO_CHECKSUM_MAGIC);
}
/* verify checksums */
ibool corrupted = buf_page_is_corrupted(false, src_frame, page_size, false);
/** restore frame & algorithm */
srv_checksum_algorithm = save_checksum_algorithm;
mach_write_to_4(const_cast<byte*>(src_frame) +
FIL_PAGE_SPACE_OR_CHKSUM,
stored_pre_encryption);
mach_write_to_4(const_cast<byte*>(src_frame) +
UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
checksum_field2);
return (!corrupted);
}
/***********************************************************************/
/** A copy of global key state */
......@@ -2671,3 +2598,93 @@ fil_space_get_scrub_status(
return crypt_data == NULL ? 1 : 0;
}
#endif /* UNIV_INNOCHECKSUM */
/*********************************************************************
Verify checksum for a page (iff it's encrypted)
NOTE: currently this function can only be run in single threaded mode
as it modifies srv_checksum_algorithm (temporarily)
@param[in] src_fame page to verify
@param[in] page_size page_size
@param[in] page_no page number of given read_buf
@param[in] strict_check true if strict-check option is enabled
@return true if page is encrypted AND OK, false otherwise */
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*============================*/
const byte* src_frame, /*!< in: page the verify */
const page_size_t& page_size /*!< in: page size */
#ifdef UNIV_INNOCHECKSUM
,uintmax_t page_no,
bool strict_check
#endif /* UNIV_INNOCHECKSUM */
)
{
// key version
uint key_version = mach_read_from_4(
src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
if (key_version == 0) {
return false; // unencrypted page
}
/* "trick" the normal checksum routines by storing the post-encryption
* checksum into the normal checksum field allowing for reuse of
* the normal routines */
// post encryption checksum
ib_uint32_t stored_post_encryption = mach_read_from_4(
src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
// save pre encryption checksum for restore in end of this function
ib_uint32_t stored_pre_encryption = mach_read_from_4(
src_frame + FIL_PAGE_SPACE_OR_CHKSUM);
ib_uint32_t checksum_field2 = mach_read_from_4(
src_frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
/** prepare frame for usage of normal checksum routines */
mach_write_to_4(const_cast<byte*>(src_frame) + FIL_PAGE_SPACE_OR_CHKSUM,
stored_post_encryption);
/* NOTE: this function is (currently) only run when restoring
* dblwr-buffer, server is single threaded so it's safe to modify
* srv_checksum_algorithm */
srv_checksum_algorithm_t save_checksum_algorithm =
(srv_checksum_algorithm_t)srv_checksum_algorithm;
if (!page_size.is_compressed() &&
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
/* handle ALGORITHM_INNODB specially,
* "downgrade" to ALGORITHM_INNODB and store BUF_NO_CHECKSUM_MAGIC
* checksum_field2 is sort of pointless anyway...
*/
srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB;
mach_write_to_4(const_cast<byte*>(src_frame) +
UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
BUF_NO_CHECKSUM_MAGIC);
}
/* verify checksums */
bool corrupted = buf_page_is_corrupted(false, src_frame,
page_size, false
#ifdef UNIV_INNOCHECKSUM
,page_no, strict_check, false, NULL
#endif /* UNIV_INNOCHECKSUM */
);
/** restore frame & algorithm */
srv_checksum_algorithm = save_checksum_algorithm;
mach_write_to_4(const_cast<byte*>(src_frame) +
FIL_PAGE_SPACE_OR_CHKSUM,
stored_pre_encryption);
mach_write_to_4(const_cast<byte*>(src_frame) +
UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
checksum_field2);
return (!corrupted);
}
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -1718,13 +1718,14 @@ fil_space_create(
fil_system->max_assigned_id = id;
}
#ifdef UNIV_DEBUG
if (crypt_data) {
space->read_page0 = true;
/* If table could be encrypted print info */
ib::info() << "Tablespace ID " << id << " name " << space->name
<< ":" << fil_crypt_get_mode(crypt_data)
<< " " << fil_crypt_get_type(crypt_data);
}
#endif
mutex_exit(&fil_system->mutex);
......
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -190,9 +190,6 @@ struct fil_space_t {
/** True if we have already printed compression failure */
bool printed_compression_failure;
/** True if page 0 of tablespace is read */
bool read_page0;
/** Release the reserved free extents.
@param[in] n_reserved number of reserved extents */
void release_free_extents(ulint n_reserved);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment