Skip to content

Commit 8a42ad7

Browse files
committed
MDEV-13834 10.2 wrongly recognizes 10.1.10 innodb_encrypt_log=ON data as after-crash and refuses to start
infos[]: Allocate enough entries to accommodate all keys from both checkpoint pages. infos_used: The size of infos[]. get_crypt_info(): Merge to the only caller, log_crypt_101_read_block(). log_crypt_101_read_block(): Do not validate the log block checksum, because it will not be valid when upgrading from MariaDB 10.1.10. Instead, check that the encryption key exists. log_crypt_101_read_checkpoint(): Append to infos[] instead of overwriting.
1 parent 1a8afb4 commit 8a42ad7

File tree

1 file changed

+31
-36
lines changed

1 file changed

+31
-36
lines changed

storage/innobase/log/log0crypt.cc

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ struct crypt_info_t {
6161
static crypt_info_t info;
6262

6363
/** Crypt info when upgrading from 10.1 */
64-
static crypt_info_t infos[5];
64+
static crypt_info_t infos[5 * 2];
65+
/** First unused slot in infos[] */
66+
static size_t infos_used;
6567

6668
/*********************************************************************//**
6769
Get a log block's start lsn.
@@ -79,28 +81,6 @@ log_block_get_start_lsn(
7981
return start_lsn;
8082
}
8183

82-
/*********************************************************************//**
83-
Get crypt info from checkpoint.
84-
@return a crypt info or NULL if not present. */
85-
static
86-
const crypt_info_t*
87-
get_crypt_info(ulint checkpoint_no)
88-
{
89-
/* a log block only stores 4-bytes of checkpoint no */
90-
checkpoint_no &= 0xFFFFFFFF;
91-
for (unsigned i = 0; i < 5; i++) {
92-
const crypt_info_t* it = &infos[i];
93-
94-
if (it->key_version && it->checkpoint_no == checkpoint_no) {
95-
return it;
96-
}
97-
}
98-
99-
/* If checkpoint contains more than one key and we did not
100-
find the correct one use the first one. */
101-
return infos;
102-
}
103-
10484
/** Encrypt or decrypt log blocks.
10585
@param[in,out] buf log blocks to encrypt or decrypt
10686
@param[in] lsn log sequence number of the start of the buffer
@@ -165,9 +145,7 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt)
165145
@param[in,out] info encryption key
166146
@param[in] upgrade whether to use the key in MariaDB 10.1 format
167147
@return whether the operation was successful */
168-
static
169-
bool
170-
init_crypt_key(crypt_info_t* info, bool upgrade = false)
148+
static bool init_crypt_key(crypt_info_t* info, bool upgrade = false)
171149
{
172150
byte mysqld_key[MY_AES_MAX_KEY_LENGTH];
173151
uint keylen = sizeof mysqld_key;
@@ -252,8 +230,20 @@ log_crypt_101_read_checkpoint(const byte* buf)
252230
const size_t n = *buf++ == 2 ? std::min(unsigned(*buf++), 5U) : 0;
253231

254232
for (size_t i = 0; i < n; i++) {
255-
struct crypt_info_t& info = infos[i];
256-
info.checkpoint_no = mach_read_from_4(buf);
233+
struct crypt_info_t& info = infos[infos_used];
234+
unsigned checkpoint_no = mach_read_from_4(buf);
235+
for (size_t j = 0; j < infos_used; j++) {
236+
if (infos[j].checkpoint_no == checkpoint_no) {
237+
/* Do not overwrite an existing slot. */
238+
goto next_slot;
239+
}
240+
}
241+
if (infos_used >= UT_ARR_SIZE(infos)) {
242+
ut_ad(!"too many checkpoint pages");
243+
goto next_slot;
244+
}
245+
infos_used++;
246+
info.checkpoint_no = checkpoint_no;
257247
info.key_version = mach_read_from_4(buf + 4);
258248
memcpy(info.crypt_msg.bytes, buf + 8, sizeof info.crypt_msg);
259249
memcpy(info.crypt_nonce.bytes, buf + 24,
@@ -262,6 +252,7 @@ log_crypt_101_read_checkpoint(const byte* buf)
262252
if (!init_crypt_key(&info, true)) {
263253
return false;
264254
}
255+
next_slot:
265256
buf += 4 + 4 + 2 * MY_AES_BLOCK_SIZE;
266257
}
267258

@@ -277,13 +268,19 @@ log_crypt_101_read_block(byte* buf)
277268
{
278269
ut_ad(log_block_calc_checksum_format_0(buf)
279270
!= log_block_get_checksum(buf));
280-
const crypt_info_t* info = get_crypt_info(
281-
log_block_get_checkpoint_no(buf));
282-
283-
if (!info || info->key_version == 0) {
284-
return false;
271+
const uint32_t checkpoint_no
272+
= uint32_t(log_block_get_checkpoint_no(buf));
273+
const crypt_info_t* info = infos;
274+
for (const crypt_info_t* const end = info + infos_used; info < end;
275+
info++) {
276+
if (info->key_version
277+
&& info->checkpoint_no == checkpoint_no) {
278+
goto found;
279+
}
285280
}
286281

282+
return false;
283+
found:
287284
byte dst[OS_FILE_LOG_BLOCK_SIZE];
288285
uint dst_len;
289286
byte aes_ctr_iv[MY_AES_BLOCK_SIZE];
@@ -312,9 +309,7 @@ log_crypt_101_read_block(byte* buf)
312309
LOG_DEFAULT_ENCRYPTION_KEY,
313310
info->key_version);
314311

315-
if (rc != MY_AES_OK || dst_len != src_len
316-
|| log_block_calc_checksum_format_0(dst)
317-
!= log_block_get_checksum(dst)) {
312+
if (rc != MY_AES_OK || dst_len != src_len) {
318313
return false;
319314
}
320315

0 commit comments

Comments
 (0)