Skip to content

Commit de8d57e

Browse files
committed
MDEV-23447 SIGSEGV in fil_system_t::keyrotate_next()
fil_system_t::keyrotate_next(): If space && space->is_in_rotation_list does not hold, iterate from the start of the list. In debug builds, we would typically have hit SIGSEGV because the iterator would have wrapped a null pointer. It might also be that we are dereferencing a stale pointer. There is no test case, because the encryption is very nondeterministic in nature, due to the use of background threads. This scenario can be hit by setting the following: SET GLOBAL innodb_encryption_threads=5; SET GLOBAL innodb_encryption_rotate_key_age=0;
1 parent 31aef3a commit de8d57e

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

storage/innobase/fil/fil0crypt.cc

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,29 +1388,34 @@ the encryption parameters were changed
13881388
inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
13891389
bool recheck, bool encrypt)
13901390
{
1391-
ut_ad(mutex_own(&fil_system->mutex));
1391+
ut_ad(mutex_own(&mutex));
13921392

13931393
sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it=
1394-
space ? space : fil_system->rotation_list.begin();
1394+
space && space->is_in_rotation_list ? space : rotation_list.begin();
13951395
const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end=
1396-
fil_system->rotation_list.end();
1396+
rotation_list.end();
13971397

13981398
if (space)
13991399
{
1400-
while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
1400+
const bool released= !--space->n_pending_ops;
14011401

1402-
/* If one of the encryption threads already started the encryption
1403-
of the table then don't remove the unencrypted spaces from rotation list
1404-
1405-
If there is a change in innodb_encrypt_tables variables value then
1406-
don't remove the last processed tablespace from the rotation list. */
1407-
if (!--space->n_pending_ops &&
1408-
(!recheck || space->crypt_data) && !encrypt == !srv_encrypt_tables &&
1409-
space->is_in_rotation_list)
1402+
if (space->is_in_rotation_list)
14101403
{
1411-
ut_a(!fil_system->rotation_list.empty());
1412-
fil_system->rotation_list.remove(*space);
1413-
space->is_in_rotation_list= false;
1404+
while (++it != end &&
1405+
(!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
1406+
1407+
/* If one of the encryption threads already started the encryption
1408+
of the table then don't remove the unencrypted spaces from rotation list
1409+
1410+
If there is a change in innodb_encrypt_tables variables value then
1411+
don't remove the last processed tablespace from the rotation list. */
1412+
if (released && (!recheck || space->crypt_data) &&
1413+
!encrypt == !srv_encrypt_tables)
1414+
{
1415+
ut_a(!rotation_list.empty());
1416+
rotation_list.remove(*space);
1417+
space->is_in_rotation_list= false;
1418+
}
14141419
}
14151420
}
14161421

0 commit comments

Comments
 (0)