Skip to content

Commit 9cdf494

Browse files
Jan Lindströmvuvova
authored andcommitted
Fixed XtraDB implementation of encryption and page encryption.
1 parent d7d589d commit 9cdf494

27 files changed

+331
-927
lines changed

mysql-test/r/information_schema_all_engines.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,5 +417,5 @@ Wildcard: inf_rmation_schema
417417
| information_schema |
418418
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
419419
table_schema count(*)
420-
information_schema59
420+
information_schema58
421421
mysql 30

storage/innobase/buf/buf0buf.cc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5668,9 +5668,6 @@ buf_page_encrypt_before_write(
56685668
mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
56695669
ut_ad(key_version == 0 || key_version >= bpage->key_version);
56705670
bpage->key_version = key_version;
5671-
5672-
// return dst_frame which will be written
5673-
return dst_frame;
56745671
} else {
56755672
// We do compression and encryption later on os0file.cc
56765673
dst_frame = (byte *)src_frame;
@@ -5765,10 +5762,21 @@ buf_page_decrypt_after_read(
57655762

57665763
if (key_version == 0) {
57675764
/* the page we read is unencrypted */
5768-
if (dst_frame != src_frame) {
5769-
/* but we had allocated a crypt_buf */
5770-
// TODO: Can this be avoided ?
5771-
memcpy(dst_frame, src_frame, size);
5765+
5766+
if (fil_page_is_compressed(dst_frame)) {
5767+
if (bpage->comp_buf_free == NULL) {
5768+
bpage->comp_buf_free = (byte *)malloc(UNIV_PAGE_SIZE*2);
5769+
// TODO: is 4k aligment enough ?
5770+
bpage->comp_buf = (byte*)ut_align(bpage->comp_buf_free, UNIV_PAGE_SIZE);
5771+
}
5772+
5773+
fil_decompress_page(bpage->comp_buf, dst_frame, size, NULL);
5774+
} else {
5775+
if (dst_frame != src_frame) {
5776+
/* but we had allocated a crypt_buf */
5777+
// TODO: Can this be avoided ?
5778+
memcpy(dst_frame, src_frame, size);
5779+
}
57725780
}
57735781
} else {
57745782
/* the page we read is encrypted */
@@ -5798,6 +5806,7 @@ buf_page_decrypt_after_read(
57985806
fil_decompress_page(bpage->comp_buf, dst_frame, size, NULL);
57995807
}
58005808
}
5809+
58015810
bpage->key_version = key_version;
58025811

58035812
if (bpage->crypt_buf_free != NULL) {
@@ -5806,6 +5815,14 @@ buf_page_decrypt_after_read(
58065815
bpage->crypt_buf = NULL;
58075816
bpage->crypt_buf_free = NULL;
58085817
}
5818+
5819+
if (bpage->comp_buf_free != NULL) {
5820+
// free temp page
5821+
free(bpage->comp_buf_free);
5822+
bpage->comp_buf = NULL;
5823+
bpage->comp_buf_free = NULL;
5824+
}
5825+
58095826
return (TRUE);
58105827
}
58115828

storage/innobase/fil/fil0fil.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,7 +1923,7 @@ fil_check_first_page(
19231923
check for reading the first page should intentionally fail
19241924
with "can not decrypt" message. */
19251925
page_is_encrypted = fil_page_encryption_status(page);
1926-
if ((page_is_encrypted == PAGE_ENCRYPTION_KEY_MISSING) && page_is_encrypted) {
1926+
if (page_is_encrypted == PAGE_ENCRYPTION_KEY_MISSING && page_is_encrypted) {
19271927
page_is_encrypted = 1;
19281928
} else {
19291929
page_is_encrypted = 0;
@@ -5841,7 +5841,8 @@ fil_io(
58415841
if (!ret) {
58425842
return(DB_OUT_OF_FILE_SPACE);
58435843
} else {
5844-
}return(DB_SUCCESS);
5844+
return(DB_SUCCESS);
5845+
}
58455846
}
58465847

58475848
#ifndef UNIV_HOTBACKUP

storage/innobase/include/fil0pageencryption.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ Helper functions for encryption/decryption page data on to table space.
3636
Created 08/25/2014
3737
***********************************************************************/
3838

39-
40-
/******************************PAGE_ENCRYPTION_ERROR*************************************//**
39+
/*******************************************************************//**
40+
Find out whether the page is page encrypted
4141
Returns the page encryption flag of the space, or false if the space
4242
is not encrypted. The tablespace must be cached in the memory cache.
4343
@return true if page encrypted, false if not or space not found */
4444
ibool
4545
fil_space_is_page_encrypted(
46-
/*=========================*/
46+
/*========================*/
4747
ulint id);/*!< in: space id */
4848

4949
/*******************************************************************//**
@@ -70,7 +70,7 @@ Find out whether the page can be decrypted
7070
UNIV_INLINE
7171
ulint
7272
fil_page_encryption_status(
73-
/*===================*/
73+
/*=======================*/
7474
const byte *buf);/*!< in: page */
7575

7676
#endif // fil0pageencryption_h

storage/innobase/os/os0file.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ struct os_aio_slot_t{
252252
byte* tmp_encryption_buf; /*!< a temporal buffer used by page encryption */
253253

254254
ibool page_compression_success;
255+
/*!< TRUE if page compression was successfull, false if not */
255256
ibool page_encryption_success;
256-
/*!< TRUE if page compression was
257-
successfull, false if not */
257+
/*!< TRUE if page encryption was successfull, false if not */
258258

259259
lsn_t lsn; /* lsn of the newest modification */
260260

@@ -4698,10 +4698,6 @@ os_aio_array_reserve_slot(
46984698

46994699
}
47004700

4701-
//if (srv_encrypt_tables) {
4702-
//page_encryption = TRUE;
4703-
//}
4704-
47054701
/* If the space is page encryption and this is write operation
47064702
then we encrypt the page */
47074703
if (message1 && type == OS_FILE_WRITE && page_encryption ) {

storage/xtradb/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,6 @@ SET(INNOBASE_SOURCES
363363
eval/eval0proc.cc
364364
fil/fil0fil.cc
365365
fil/fil0pagecompress.cc
366-
fil/fil0pageencryption.cc
367366
fil/fil0crypt.cc
368367
fsp/fsp0fsp.cc
369368
fut/fut0fut.cc

storage/xtradb/buf/buf0buf.cc

Lines changed: 103 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Created 11/5/1995 Heikki Tuuri
5959
#include "ut0byte.h"
6060

6161
#include "fil0pageencryption.h"
62+
#include "fil0pagecompress.h"
6263

6364

6465
/* prototypes for new functions added to ha_innodb.cc */
@@ -574,7 +575,7 @@ buf_page_is_corrupted(
574575
ulint zip_size)/*!< in: size of compressed page;
575576
0 for uncompressed pages */
576577
{
577-
ulint page_encrypted = fil_page_is_encrypted(read_buf);
578+
ulint page_encrypted = fil_page_is_compressed_encrypted(read_buf) || fil_page_is_encrypted(read_buf);
578579
ulint checksum_field1;
579580
ulint checksum_field2;
580581
ibool crc32_inited = FALSE;
@@ -1080,8 +1081,11 @@ buf_block_init(
10801081
block->page.io_fix = BUF_IO_NONE;
10811082
block->page.crypt_buf = NULL;
10821083
block->page.crypt_buf_free = NULL;
1084+
block->page.comp_buf = NULL;
1085+
block->page.comp_buf_free = NULL;
10831086
block->page.key_version = 0;
10841087

1088+
10851089
block->modify_clock = 0;
10861090

10871091
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
@@ -3580,6 +3584,8 @@ buf_page_init_low(
35803584
bpage->write_size = 0;
35813585
bpage->crypt_buf = NULL;
35823586
bpage->crypt_buf_free = NULL;
3587+
bpage->comp_buf = NULL;
3588+
bpage->comp_buf_free = NULL;
35833589
bpage->key_version = 0;
35843590

35853591
HASH_INVALIDATE(bpage, hash);
@@ -5787,6 +5793,11 @@ buf_page_encrypt_before_write(
57875793
buf_page_t* bpage, /*!< in/out: buffer page to be flushed */
57885794
const byte* src_frame) /*!< in: src frame */
57895795
{
5796+
if (srv_encrypt_tables == FALSE) {
5797+
/* Encryption is disabled */
5798+
return const_cast<byte*>(src_frame);
5799+
}
5800+
57905801
if (bpage->offset == 0) {
57915802
/* Page 0 of a tablespace is not encrypted */
57925803
ut_ad(bpage->key_version == 0);
@@ -5806,6 +5817,7 @@ buf_page_encrypt_before_write(
58065817
}
58075818

58085819
ulint zip_size = buf_page_get_zip_size(bpage);
5820+
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
58095821

58105822
/**
58115823
* TODO(jonaso): figure out more clever malloc strategy
@@ -5822,18 +5834,28 @@ buf_page_encrypt_before_write(
58225834
* considered a lot.
58235835
*/
58245836

5825-
bpage->crypt_buf_free = (byte*)malloc(UNIV_PAGE_SIZE*2);
5826-
byte *dst_frame = bpage->crypt_buf = (byte *)ut_align(bpage->crypt_buf_free, UNIV_PAGE_SIZE);
5837+
if (bpage->crypt_buf_free == NULL) {
5838+
bpage->crypt_buf_free = (byte*)malloc(page_size*2);
5839+
// TODO: Is 4k aligment enough ?
5840+
bpage->crypt_buf = (byte *)ut_align(bpage->crypt_buf_free, page_size);
5841+
}
58275842

5828-
// encrypt page content
5829-
fil_space_encrypt(bpage->space, bpage->offset,
5830-
bpage->newest_modification,
5831-
src_frame, zip_size, dst_frame, 0);
5843+
byte *dst_frame = bpage->crypt_buf;
58325844

5833-
unsigned key_version =
5834-
mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
5835-
ut_ad(key_version == 0 || key_version >= bpage->key_version);
5836-
bpage->key_version = key_version;
5845+
if (!fil_space_is_page_compressed(bpage->space)) {
5846+
// encrypt page content
5847+
fil_space_encrypt(bpage->space, bpage->offset,
5848+
bpage->newest_modification,
5849+
src_frame, zip_size, dst_frame, 0);
5850+
5851+
unsigned key_version =
5852+
mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
5853+
ut_ad(key_version == 0 || key_version >= bpage->key_version);
5854+
bpage->key_version = key_version;
5855+
} else {
5856+
// We do compression and encryption later on os0file.cc
5857+
dst_frame = (byte *)src_frame;
5858+
}
58375859

58385860
// return dst_frame which will be written
58395861
return dst_frame;
@@ -5852,6 +5874,13 @@ buf_page_encrypt_after_write(
58525874
bpage->crypt_buf_free = NULL;
58535875
bpage->crypt_buf = NULL;
58545876
}
5877+
5878+
if (bpage->comp_buf_free != NULL) {
5879+
free(bpage->comp_buf_free);
5880+
bpage->comp_buf_free = NULL;
5881+
bpage->comp_buf = NULL;
5882+
}
5883+
58555884
return (TRUE);
58565885
}
58575886

@@ -5861,27 +5890,28 @@ Allocates memory to read in an encrypted page
58615890
byte*
58625891
buf_page_decrypt_before_read(
58635892
/*=========================*/
5864-
buf_page_t* bpage) /*!< in/out: buffer page to be read */
5893+
buf_page_t* bpage, /*!< in/out: buffer page to be read */
5894+
ulint zip_size) /*!< in: compressed page size, or 0 */
58655895
{
5866-
ulint zip_size = buf_page_get_zip_size(bpage);
5867-
5868-
if (bpage->offset == 0) {
5869-
/* File header pages are not encrypted */
5870-
unencrypted:
5871-
if (zip_size)
5872-
return bpage->zip.data;
5873-
else
5874-
return ((buf_block_t*) bpage)->frame;
5875-
}
5876-
5877-
if (fil_space_check_encryption_read(bpage->space) == false) {
5878-
goto unencrypted;
5879-
}
5896+
ulint size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
58805897

5881-
// allocate buffer to read data into
5882-
bpage->crypt_buf_free = (byte*)malloc(UNIV_PAGE_SIZE*2);
5883-
bpage->crypt_buf = (byte*)ut_align(bpage->crypt_buf_free, UNIV_PAGE_SIZE);
5884-
return bpage->crypt_buf;
5898+
/*
5899+
Here we only need to allocate space for not header pages
5900+
in case of file space encryption. Table encryption is handled
5901+
later.
5902+
*/
5903+
if (!srv_encrypt_tables || bpage->offset == 0 ||
5904+
fil_space_check_encryption_read(bpage->space) == false)
5905+
return zip_size ? bpage->zip.data : ((buf_block_t*) bpage)->frame;
5906+
5907+
if (bpage->crypt_buf_free == NULL)
5908+
{
5909+
// allocate buffer to read data into
5910+
bpage->crypt_buf_free = (byte*)malloc(size*2);
5911+
// TODO: Is 4K aligment enough ?
5912+
bpage->crypt_buf = (byte*)ut_align(bpage->crypt_buf_free, size);
5913+
}
5914+
return bpage->crypt_buf;
58855915
}
58865916

58875917
/********************************************************************//**
@@ -5893,28 +5923,41 @@ buf_page_decrypt_after_read(
58935923
buf_page_t* bpage) /*!< in/out: buffer page read from disk */
58945924
{
58955925
ut_ad(bpage->key_version == 0);
5926+
ulint zip_size = buf_page_get_zip_size(bpage);
5927+
ulint size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
5928+
5929+
byte* dst_frame = (zip_size) ? bpage->zip.data :
5930+
((buf_block_t*) bpage)->frame;
5931+
58965932
if (bpage->offset == 0) {
58975933
/* File header pages are not encrypted */
58985934
ut_a(bpage->crypt_buf == NULL);
58995935
return (TRUE);
59005936
}
59015937

5902-
ulint zip_size = buf_page_get_zip_size(bpage);
5903-
ulint size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
5904-
5905-
byte* dst_frame = (zip_size) ? bpage->zip.data :
5906-
((buf_block_t*) bpage)->frame;
59075938
const byte* src_frame = bpage->crypt_buf != NULL ?
59085939
bpage->crypt_buf : dst_frame;
59095940

59105941
unsigned key_version =
59115942
mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
5943+
bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame);
59125944

59135945
if (key_version == 0) {
59145946
/* the page we read is unencrypted */
5915-
if (dst_frame != src_frame) {
5916-
/* but we had allocated a crypt_buf */
5917-
memcpy(dst_frame, src_frame, size);
5947+
if (fil_page_is_compressed(dst_frame)) {
5948+
if (bpage->comp_buf_free == NULL) {
5949+
bpage->comp_buf_free = (byte *)malloc(UNIV_PAGE_SIZE*2);
5950+
// TODO: is 4k aligment enough ?
5951+
bpage->comp_buf = (byte*)ut_align(bpage->comp_buf_free, UNIV_PAGE_SIZE);
5952+
}
5953+
5954+
fil_decompress_page(bpage->comp_buf, dst_frame, size, NULL);
5955+
} else {
5956+
if (dst_frame != src_frame) {
5957+
/* but we had allocated a crypt_buf */
5958+
// TODO: Can this be avoided ?
5959+
memcpy(dst_frame, src_frame, size);
5960+
}
59185961
}
59195962
} else {
59205963
/* the page we read is encrypted */
@@ -5923,13 +5966,27 @@ buf_page_decrypt_after_read(
59235966
* malloc a buffer, copy page to it
59245967
* and then decrypt from that into real page*/
59255968
bpage->crypt_buf_free = (byte *)malloc(UNIV_PAGE_SIZE*2);
5969+
// TODO: is 4k aligment enough ?
59265970
src_frame = bpage->crypt_buf = (byte*)ut_align(bpage->crypt_buf_free, UNIV_PAGE_SIZE);
59275971
memcpy(bpage->crypt_buf, dst_frame, size);
59285972
}
59295973
/* decrypt from src_frame to dst_frame */
59305974
fil_space_decrypt(bpage->space,
59315975
src_frame, size, dst_frame);
5976+
5977+
/* decompress from dst_frame to comp_buf and then copy to
5978+
buffer pool */
5979+
if (page_compressed_encrypted) {
5980+
if (bpage->comp_buf_free == NULL) {
5981+
bpage->comp_buf_free = (byte *)malloc(UNIV_PAGE_SIZE*2);
5982+
// TODO: is 4k aligment enough ?
5983+
bpage->comp_buf = (byte*)ut_align(bpage->comp_buf_free, UNIV_PAGE_SIZE);
5984+
}
5985+
5986+
fil_decompress_page(bpage->comp_buf, dst_frame, size, NULL);
5987+
}
59325988
}
5989+
59335990
bpage->key_version = key_version;
59345991

59355992
if (bpage->crypt_buf_free != NULL) {
@@ -5938,6 +5995,14 @@ buf_page_decrypt_after_read(
59385995
bpage->crypt_buf = NULL;
59395996
bpage->crypt_buf_free = NULL;
59405997
}
5998+
5999+
if (bpage->comp_buf_free != NULL) {
6000+
// free temp page
6001+
free(bpage->comp_buf_free);
6002+
bpage->comp_buf = NULL;
6003+
bpage->comp_buf_free = NULL;
6004+
}
6005+
59416006
return (TRUE);
59426007
}
59436008

0 commit comments

Comments
 (0)