As noted in MDEV-11974, the InnoDB encryption that was introduced in MariaDB Server 10.1 is incompatible with the SPATIAL INDEX implementation of MySQL 5.7 that was merged into MariaDB Server 10.2.2.
MDEV-11974 was addressed by preventing or disabling the encryption of spatial indexes. For a later server release, we should come up with an encryption solution that works also on spatial indexes.
Attachments
Issue Links
causes
MDEV-20383Use of uninitialized value in Datafile::find_space_id() for ROW_FORMAT=COMPRESSED
Closed
MDEV-23199page_compression flag is missing for full_crc32 tablespace
Closed
MDEV-23254Replace FSP_FLAGS_HAS_PAGE_COMPRESSION with fil_space_t::is_compressed
Closed
MDEV-26148SEGV or Assertion `!page_is_comp(page) == !(index->table)->not_redundant()'
Closed
is caused by
MDEV-11974Disable encryption of spatial indexes in MariaDB 10.2
Closed
relates to
MDEV-18097Indicate which InnoDB data files are zero-initialized
Closed
MDEV-18644Support FULL_CRC32 for compressed pages.
Closed
MDEV-19534Make innodb_checksum_algorithm=full_crc32 by default, and remove innodb_checksums
Surprises with unencrypted data (minimum bounding rectangles and PRIMARY KEY values) might be possible with innodb_encrypt_tables=ON.
I think that we can do the following:
Introduce a new page type code for encrypted spatial index.
Before encryption, store the Split Sequence Number (SSN) in the space that was reserved for the strings "infimum" and "supremum". Zero-fill the rest of the strings, similar to how MDEV-15562 did it for the clustered index root page.
When decrypting, restore the SSN to the correct place, and fill in the strings "infimum" and "supremum".
On the encrypted page, the encryption parameters will be in the familiar location (the same location that was repurposed for the SSN in the unencrypted spatial index page).
Thanks to the new page type code, the index pages should be unaccessible in earlier versions of MariaDB.
As part of this fix, the creation of encrypted tables with SPATIAL INDEX must be re-enabled.
Marko Mäkelä
added a comment - A CREATE TABLE or ALTER TABLE of an encrypted table with SPATIAL INDEX was prevented in MDEV-11974 , at least in some tested cases . There was a refinement for ALTER TABLE .
Surprises with unencrypted data (minimum bounding rectangles and PRIMARY KEY values) might be possible with innodb_encrypt_tables=ON .
I think that we can do the following:
Introduce a new page type code for encrypted spatial index.
Before encryption, store the Split Sequence Number (SSN) in the space that was reserved for the strings "infimum" and "supremum" . Zero-fill the rest of the strings, similar to how MDEV-15562 did it for the clustered index root page.
When decrypting, restore the SSN to the correct place, and fill in the strings "infimum" and "supremum" .
On the encrypted page, the encryption parameters will be in the familiar location (the same location that was repurposed for the SSN in the unencrypted spatial index page).
Thanks to the new page type code, the index pages should be unaccessible in earlier versions of MariaDB.
As part of this fix, the creation of encrypted tables with SPATIAL INDEX must be re-enabled.
It turns out that even in root pages, the first 4 bytes of each field are redundant:
#define FSEG_HDR_SPACE 0 /*!< space id of the inode */
#define FSEG_HDR_PAGE_NO 4 /*!< page number of the inode */
#define FSEG_HDR_OFFSET 8 /*!< byte offset of the inode */
#define FSEG_HEADER_SIZE 10 /*!< Length of the file system
header, in bytes */
Let us repurpose the first 4 bytes of PAGE_BTR_SEG_TOP in the encrypted copy of the page, to store the encrypted 32-bit split sequence number (SSN). The encryption algorithm should be like this:
encrypt up to PAGE_BTR_SEG_TOP
encrypt a buffer that holds the SSN in big-endian format
encrypt from PAGE_BTR_SEG_TOP + 4 onwards
When decrypting, we would copy the SSN into the right place in the unencrypted page, and also restore the original contents:
Marko Mäkelä
added a comment - My idea of repurposing the fields "infimum" and "supremum" will not work with ROW_FORMAT=COMPRESSED tables, because those pages omit these records.
But, the following fields are unused in all index pages except the root pages:
#define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in
a B-tree: defined only on the root page of a
B-tree, but not in the root of an ibuf tree */
#define PAGE_BTR_IBUF_FREE_LIST PAGE_BTR_SEG_LEAF
#define PAGE_BTR_IBUF_FREE_LIST_NODE PAGE_BTR_SEG_LEAF
/* in the place of PAGE_BTR_SEG_LEAF and _TOP
there is a free list base node if the page is
the root page of an ibuf tree, and at the same
place is the free list node if the page is in
a free list */
#define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE)
/* file segment header for the non-leaf pages
in a B-tree: defined only on the root page of
a B-tree, but not in the root of an ibuf
tree */
It turns out that even in root pages, the first 4 bytes of each field are redundant:
#define FSEG_HDR_SPACE 0 /*!< space id of the inode */
#define FSEG_HDR_PAGE_NO 4 /*!< page number of the inode */
#define FSEG_HDR_OFFSET 8 /*!< byte offset of the inode */
#define FSEG_HEADER_SIZE 10 /*!< Length of the file system
header, in bytes */
Let us repurpose the first 4 bytes of PAGE_BTR_SEG_TOP in the encrypted copy of the page, to store the encrypted 32-bit split sequence number (SSN). The encryption algorithm should be like this:
encrypt up to PAGE_BTR_SEG_TOP
encrypt a buffer that holds the SSN in big-endian format
encrypt from PAGE_BTR_SEG_TOP + 4 onwards
When decrypting, we would copy the SSN into the right place in the unencrypted page, and also restore the original contents:
memcpy (block->frame + PAGE_BTR_SEG_TOP, block->frame + PAGE_BTR_SEG_LEAF, 4);
It would be good to add
ut_ad(! memcmp (block->frame + PAGE_BTR_SEG_TOP, block->frame + PAGE_BTR_SEG_LEAF, 4));
to the encryption code path.
We now have a patch that implements my suggestion above. This patch could theoretically backported to 10.2 and 10.3. If that patch were applied, an IMPORT TABLESPACE or a downgrade to an earlier version would seemingly succeed, but we would get crashes somewhere later when the encrypted spatial index is being accessed.
During the recent work on MDEV-12112 and MDEV-17957, an alternative (and in my opinion better) approach occurred to me.
Instead of shuffling bytes in multiple higher-level places of InnoDB, I think that the clean solution is to introduce a new encrypted file format, identified by a new flag in FSP_SPACE_FLAGS that would also prevent downgrading to earlier versions of MariaDB. This flag would indicate the following:
Unused bytes on data pages are initialized to zero. (As noted in MDEV-18097, files created before this change in MySQL 5.1.48 could contain any garbage values, limiting the ability to repurpose pages.)
A new page checksum algorithm is always being used, and it cannot be overridden by innodb_checksum_algorithm.
Only one page_compressed algorithm is allowed, and it cannot be overridden. The page header will include the checksum and the compressed size of the page.
Only one checksum will be computed on the page payload (after any compression or encryption).
The key_version will be stored in the first 4 bytes of each page. So, there is no collision with SPATIAL INDEX.
We’d introduce a new (and default) configuration parameter value innodb_checksum_algorithm=full_crc32 (or a better name) with a strict_ counterpart, which would refuse to open old data files.
The non-strict variant would open old tablespaces fine, but it would create new files with the new bit in FSP_SPACE_FLAGS set, preventing a downgrade.
If compatibility with older MariaDB or MySQL versions is desired, then innodb_checksum_algorithm=crc32 can be set. In this case, any pre-existing new-checksum files would be opened fine, but they would keep using the new format. Any new created files would use the old format and the configured innodb_checksum_algorithm.
Setting innodb_checksum_algorithm to something else than the default value (or its strict_ counterpart) would issue a deprecation warning, because we would want to remove the old algorithms and formats in some future release of MariaDB.
To implement this, we’d have to do a few things differently when decrypting or encrypting pages, based on fil_space_t::flags. A member function could be introduced for those checks, something like this:
Marko Mäkelä
added a comment - We now have a patch that implements my suggestion above. This patch could theoretically backported to 10.2 and 10.3. If that patch were applied, an IMPORT TABLESPACE or a downgrade to an earlier version would seemingly succeed, but we would get crashes somewhere later when the encrypted spatial index is being accessed.
During the recent work on MDEV-12112 and MDEV-17957 , an alternative (and in my opinion better) approach occurred to me.
Instead of shuffling bytes in multiple higher-level places of InnoDB, I think that the clean solution is to introduce a new encrypted file format, identified by a new flag in FSP_SPACE_FLAGS that would also prevent downgrading to earlier versions of MariaDB. This flag would indicate the following:
Unused bytes on data pages are initialized to zero. (As noted in MDEV-18097 , files created before this change in MySQL 5.1.48 could contain any garbage values, limiting the ability to repurpose pages.)
A new page checksum algorithm is always being used, and it cannot be overridden by innodb_checksum_algorithm .
Only one page_compressed algorithm is allowed, and it cannot be overridden. The page header will include the checksum and the compressed size of the page.
Only one checksum will be computed on the page payload (after any compression or encryption).
The key_version will be stored in the first 4 bytes of each page. So, there is no collision with SPATIAL INDEX .
We’d introduce a new (and default) configuration parameter value
innodb_checksum_algorithm=full_crc32 (or a better name) with a strict_ counterpart, which would refuse to open old data files.
The non-strict variant would open old tablespaces fine, but it would create new files with the new bit in FSP_SPACE_FLAGS set, preventing a downgrade.
If compatibility with older MariaDB or MySQL versions is desired, then innodb_checksum_algorithm=crc32 can be set. In this case, any pre-existing new-checksum files would be opened fine, but they would keep using the new format. Any new created files would use the old format and the configured innodb_checksum_algorithm .
Setting innodb_checksum_algorithm to something else than the default value (or its strict_ counterpart) would issue a deprecation warning, because we would want to remove the old algorithms and formats in some future release of MariaDB.
To implement this, we’d have to do a few things differently when decrypting or encrypting pages, based on fil_space_t::flags . A member function could be introduced for those checks, something like this:
bool use_full_checksum() const { return flags & FSP_FLAGS_FULL_CHECKSUM; }
This was pushed to MariaDB 10.4.3.
By default, encryption will not be supported on SPATIAL INDEX pages. To do that, you will have to do one of the following:
-- create new files in the new format; allow any checksum for old files
The follow-up task MDEV-18644 was filed for implementing support for page_compressed pages with this format.
ROW_FORMAT=COMPRESSED tables will not use the new format.
Marko Mäkelä
added a comment - This was pushed to MariaDB 10.4.3 .
By default, encryption will not be supported on SPATIAL INDEX pages. To do that, you will have to do one of the following:
-- create new files in the new format; allow any checksum for old files
SET GLOBAL innodb_checksum_algorithm=full_crc32;
-- equivalent to strict_crc32 for old files
SET GLOBAL innodb_checksum_algorithm=strict_full_crc32;
The follow-up task MDEV-18644 was filed for implementing support for page_compressed pages with this format.
ROW_FORMAT=COMPRESSED tables will not use the new format.
People
Marko Mäkelä
Marko Mäkelä
Votes:
1Vote for this issue
Watchers:
7Start watching this issue
Dates
Created:
Updated:
Resolved:
Git Integration
Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.
{"report":{"fcp":1619.8000001907349,"ttfb":538.6000001430511,"pageVisibility":"visible","entityId":60171,"key":"jira.project.issue.view-issue","isInitial":true,"threshold":1000,"elementTimings":{},"userDeviceMemory":8,"userDeviceProcessors":64,"apdex":0.5,"journeyId":"34e4e19b-3322-4ab7-8609-8afe5f217e34","navigationType":0,"readyForUser":1766.1000001430511,"redirectCount":0,"resourceLoadedEnd":2234.600000143051,"resourceLoadedStart":554.8000001907349,"resourceTiming":[{"duration":245.19999980926514,"initiatorType":"link","name":"https://jira.mariadb.org/s/2c21342762a6a02add1c328bed317ffd-CDN/lu2cib/820016/12ta74/0a8bac35585be7fc6c9cc5a0464cd4cf/_/download/contextbatch/css/_super/batch.css","startTime":554.8000001907349,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":554.8000001907349,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":800,"responseStart":0,"secureConnectionStart":0},{"duration":245.09999990463257,"initiatorType":"link","name":"https://jira.mariadb.org/s/7ebd35e77e471bc30ff0eba799ebc151-CDN/lu2cib/820016/12ta74/494e4c556ecbb29f90a3d3b4f09cb99c/_/download/contextbatch/css/jira.browse.project,project.issue.navigator,jira.view.issue,jira.general,jira.global,atl.general,-_super/batch.css?agile_global_admin_condition=true&jag=true&jira.create.linked.issue=true&slack-enabled=true&whisper-enabled=true","startTime":555.1000001430511,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":555.1000001430511,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":800.2000000476837,"responseStart":0,"secureConnectionStart":0},{"duration":479.69999980926514,"initiatorType":"script","name":"https://jira.mariadb.org/s/0917945aaa57108d00c5076fea35e069-CDN/lu2cib/820016/12ta74/0a8bac35585be7fc6c9cc5a0464cd4cf/_/download/contextbatch/js/_super/batch.js?locale=en","startTime":555.3000001907349,"connectEnd":555.3000001907349,"connectStart":555.3000001907349,"domainLookupEnd":555.3000001907349,"domainLookupStart":555.3000001907349,"fetchStart":555.3000001907349,"redirectEnd":0,"redirectStart":0,"requestStart":804,"responseEnd":1035,"responseStart":819.3000001907349,"secureConnectionStart":555.3000001907349},{"duration":711.6000001430511,"initiatorType":"script","name":"https://jira.mariadb.org/s/2d8175ec2fa4c816e8023260bd8c1786-CDN/lu2cib/820016/12ta74/494e4c556ecbb29f90a3d3b4f09cb99c/_/download/contextbatch/js/jira.browse.project,project.issue.navigator,jira.view.issue,jira.general,jira.global,atl.general,-_super/batch.js?agile_global_admin_condition=true&jag=true&jira.create.linked.issue=true&locale=en&slack-enabled=true&whisper-enabled=true","startTime":555.5,"connectEnd":555.5,"connectStart":555.5,"domainLookupEnd":555.5,"domainLookupStart":555.5,"fetchStart":555.5,"redirectEnd":0,"redirectStart":0,"requestStart":804.3000001907349,"responseEnd":1267.1000001430511,"responseStart":833.3000001907349,"secureConnectionStart":555.5},{"duration":287.7999999523163,"initiatorType":"script","name":"https://jira.mariadb.org/s/a9324d6758d385eb45c462685ad88f1d-CDN/lu2cib/820016/12ta74/c92c0caa9a024ae85b0ebdbed7fb4bd7/_/download/contextbatch/js/atl.global,-_super/batch.js?locale=en","startTime":555.7000000476837,"connectEnd":555.7000000476837,"connectStart":555.7000000476837,"domainLookupEnd":555.7000000476837,"domainLookupStart":555.7000000476837,"fetchStart":555.7000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":804.5,"responseEnd":843.5,"responseStart":836.1000001430511,"secureConnectionStart":555.7000000476837},{"duration":288.2999999523163,"initiatorType":"script","name":"https://jira.mariadb.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/lu2cib/820016/12ta74/1.0/_/download/batch/jira.webresources:calendar-en/jira.webresources:calendar-en.js","startTime":555.9000000953674,"connectEnd":555.9000000953674,"connectStart":555.9000000953674,"domainLookupEnd":555.9000000953674,"domainLookupStart":555.9000000953674,"fetchStart":555.9000000953674,"redirectEnd":0,"redirectStart":0,"requestStart":804.8000001907349,"responseEnd":844.2000000476837,"responseStart":839,"secureConnectionStart":555.9000000953674},{"duration":287.90000009536743,"initiatorType":"script","name":"https://jira.mariadb.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/lu2cib/820016/12ta74/1.0/_/download/batch/jira.webresources:calendar-localisation-moment/jira.webresources:calendar-localisation-moment.js","startTime":556.2000000476837,"connectEnd":556.2000000476837,"connectStart":556.2000000476837,"domainLookupEnd":556.2000000476837,"domainLookupStart":556.2000000476837,"fetchStart":556.2000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":805,"responseEnd":844.1000001430511,"responseStart":837.6000001430511,"secureConnectionStart":556.2000000476837},{"duration":246.09999990463257,"initiatorType":"link","name":"https://jira.mariadb.org/s/b04b06a02d1959df322d9cded3aeecc1-CDN/lu2cib/820016/12ta74/a2ff6aa845ffc9a1d22fe23d9ee791fc/_/download/contextbatch/css/jira.global.look-and-feel,-_super/batch.css","startTime":556.3000001907349,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":556.3000001907349,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":802.4000000953674,"responseStart":0,"secureConnectionStart":0},{"duration":275.5,"initiatorType":"script","name":"https://jira.mariadb.org/rest/api/1.0/shortcuts/820016/47140b6e0a9bc2e4913da06536125810/shortcuts.js?context=issuenavigation&context=issueaction","startTime":556.5,"connectEnd":556.5,"connectStart":556.5,"domainLookupEnd":556.5,"domainLookupStart":556.5,"fetchStart":556.5,"redirectEnd":0,"redirectStart":0,"requestStart":805.5,"responseEnd":832,"responseStart":827.2000000476837,"secureConnectionStart":556.5},{"duration":246.70000004768372,"initiatorType":"link","name":"https://jira.mariadb.org/s/3ac36323ba5e4eb0af2aa7ac7211b4bb-CDN/lu2cib/820016/12ta74/d176f0986478cc64f24226b3d20c140d/_/download/contextbatch/css/com.atlassian.jira.projects.sidebar.init,-_super,-project.issue.navigator,-jira.view.issue/batch.css?jira.create.linked.issue=true","startTime":556.7000000476837,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":556.7000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":803.4000000953674,"responseStart":0,"secureConnectionStart":0},{"duration":287,"initiatorType":"script","name":"https://jira.mariadb.org/s/5d5e8fe91fbc506585e83ea3b62ccc4b-CDN/lu2cib/820016/12ta74/d176f0986478cc64f24226b3d20c140d/_/download/contextbatch/js/com.atlassian.jira.projects.sidebar.init,-_super,-project.issue.navigator,-jira.view.issue/batch.js?jira.create.linked.issue=true&locale=en","startTime":556.9000000953674,"connectEnd":556.9000000953674,"connectStart":556.9000000953674,"domainLookupEnd":556.9000000953674,"domainLookupStart":556.9000000953674,"fetchStart":556.9000000953674,"redirectEnd":0,"redirectStart":0,"requestStart":805.8000001907349,"responseEnd":843.9000000953674,"responseStart":827.8000001907349,"secureConnectionStart":556.9000000953674},{"duration":893.9000000953674,"initiatorType":"script","name":"https://jira.mariadb.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/lu2cib/820016/12ta74/1.0/_/download/batch/jira.webresources:bigpipe-js/jira.webresources:bigpipe-js.js","startTime":558.7000000476837,"connectEnd":558.7000000476837,"connectStart":558.7000000476837,"domainLookupEnd":558.7000000476837,"domainLookupStart":558.7000000476837,"fetchStart":558.7000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":1439.5,"responseEnd":1452.6000001430511,"responseStart":1451.4000000953674,"secureConnectionStart":558.7000000476837},{"duration":1675.9000000953674,"initiatorType":"script","name":"https://jira.mariadb.org/s/d41d8cd98f00b204e9800998ecf8427e-CDN/lu2cib/820016/12ta74/1.0/_/download/batch/jira.webresources:bigpipe-init/jira.webresources:bigpipe-init.js","startTime":558.7000000476837,"connectEnd":558.7000000476837,"connectStart":558.7000000476837,"domainLookupEnd":558.7000000476837,"domainLookupStart":558.7000000476837,"fetchStart":558.7000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":2106.9000000953674,"responseEnd":2234.600000143051,"responseStart":2118.4000000953674,"secureConnectionStart":558.7000000476837},{"duration":442.59999990463257,"initiatorType":"xmlhttprequest","name":"https://jira.mariadb.org/rest/webResources/1.0/resources","startTime":1169.9000000953674,"connectEnd":1169.9000000953674,"connectStart":1169.9000000953674,"domainLookupEnd":1169.9000000953674,"domainLookupStart":1169.9000000953674,"fetchStart":1169.9000000953674,"redirectEnd":0,"redirectStart":0,"requestStart":1575.6000001430511,"responseEnd":1612.5,"responseStart":1611.2000000476837,"secureConnectionStart":1169.9000000953674},{"duration":699.7000000476837,"initiatorType":"script","name":"https://www.google-analytics.com/analytics.js","startTime":1612.7000000476837,"connectEnd":0,"connectStart":0,"domainLookupEnd":0,"domainLookupStart":0,"fetchStart":1612.7000000476837,"redirectEnd":0,"redirectStart":0,"requestStart":0,"responseEnd":2312.4000000953674,"responseStart":0,"secureConnectionStart":0}],"fetchStart":0,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"connectEnd":0,"requestStart":322,"responseStart":538,"responseEnd":541,"domLoading":549,"domInteractive":2373,"domContentLoadedEventStart":2373,"domContentLoadedEventEnd":2463,"domComplete":3523,"loadEventStart":3523,"loadEventEnd":3523,"userAgent":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)","marks":[{"name":"bigPipe.sidebar-id.start","time":2314.2000000476837},{"name":"bigPipe.sidebar-id.end","time":2315.100000143051},{"name":"bigPipe.activity-panel-pipe-id.start","time":2315.2000000476837},{"name":"bigPipe.activity-panel-pipe-id.end","time":2319.4000000953674},{"name":"activityTabFullyLoaded","time":2487.300000190735}],"measures":[],"correlationId":"77b9001449c040","effectiveType":"4g","downlink":10,"rtt":0,"serverDuration":124,"dbReadsTimeInMs":22,"dbConnsTimeInMs":31,"applicationHash":"9d11dbea5f4be3d4cc21f03a88dd11d8c8687422","experiments":[]}}
A CREATE TABLE or ALTER TABLE of an encrypted table with SPATIAL INDEX was prevented in
MDEV-11974, at least in some tested cases. There was a refinement for ALTER TABLE.Surprises with unencrypted data (minimum bounding rectangles and PRIMARY KEY values) might be possible with innodb_encrypt_tables=ON.
I think that we can do the following:
MDEV-15562did it for the clustered index root page.Thanks to the new page type code, the index pages should be unaccessible in earlier versions of MariaDB.
As part of this fix, the creation of encrypted tables with SPATIAL INDEX must be re-enabled.