Skip to content

Commit 82daaeb

Browse files
committed
Fix broken reuse of deleted entries in key map file
Since we tried to check if flags & MAP_ENTRY_EMPTY was true when searching for empty entries the code was broken since x & 0 always is false. We fix this by refactoring pg_tde_read_one_map_entry() so the filtering of the entries is done outside the function. This make implementing search for empty entries much easier.
1 parent ca37d73 commit 82daaeb

File tree

2 files changed

+25
-70
lines changed

2 files changed

+25
-70
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 25 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static TDEMapEntry *pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32
114114
static InternalKey *tde_decrypt_rel_key(TDEPrincipalKey *principal_key, TDEMapEntry *map_entry);
115115
static int pg_tde_open_file_basic(const char *tde_filename, int fileFlags, bool ignore_missing);
116116
static void pg_tde_file_header_read(const char *tde_filename, int fd, TDEFileHeader *fheader, off_t *bytes_read);
117-
static bool pg_tde_read_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset);
117+
static bool pg_tde_read_one_map_entry(int fd, TDEMapEntry *map_entry, off_t *offset);
118118
static void pg_tde_read_one_map_entry2(int keydata_fd, int32 key_index, TDEMapEntry *map_entry, Oid databaseId);
119119
static int pg_tde_open_file_read(const char *tde_filename, off_t *curr_pos);
120120
static InternalKey *pg_tde_get_key_from_cache(const RelFileLocator *rlocator, uint32 key_type);
@@ -449,16 +449,12 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_
449449
while (1)
450450
{
451451
TDEMapEntry read_map_entry;
452-
bool found;
453452

454453
prev_pos = curr_pos;
455-
found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &read_map_entry, &curr_pos);
454+
if (!pg_tde_read_one_map_entry(map_fd, &read_map_entry, &curr_pos))
455+
break;
456456

457-
/*
458-
* We either reach EOF or found an empty slot in the middle of the
459-
* file
460-
*/
461-
if (prev_pos == curr_pos || found)
457+
if (read_map_entry.flags == MAP_ENTRY_EMPTY)
462458
break;
463459
}
464460

@@ -522,16 +518,12 @@ pg_tde_write_key_map_entry_redo(const TDEMapEntry *write_map_entry, TDESignedPri
522518
while (1)
523519
{
524520
TDEMapEntry read_map_entry;
525-
bool found;
526521

527522
prev_pos = curr_pos;
528-
found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &read_map_entry, &curr_pos);
523+
if (!pg_tde_read_one_map_entry(map_fd, &read_map_entry, &curr_pos))
524+
break;
529525

530-
/*
531-
* We either reach EOF or found an empty slot in the middle of the
532-
* file
533-
*/
534-
if (prev_pos == curr_pos || found)
526+
if (read_map_entry.flags == MAP_ENTRY_EMPTY)
535527
break;
536528
}
537529

@@ -583,17 +575,13 @@ pg_tde_delete_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t
583575
*/
584576
while (1)
585577
{
586-
TDEMapEntry read_map_entry;
578+
TDEMapEntry map_entry;
587579
off_t prev_pos = curr_pos;
588580

589-
found = pg_tde_read_one_map_entry(map_fd, rlocator, MAP_ENTRY_VALID, &read_map_entry, &curr_pos);
590-
591-
/* We've reached EOF */
592-
if (curr_pos == prev_pos)
581+
if (!pg_tde_read_one_map_entry(map_fd, &map_entry, &curr_pos))
593582
break;
594583

595-
/* We found a valid entry for the relation */
596-
if (found)
584+
if (map_entry.flags != MAP_ENTRY_EMPTY && map_entry.spcOid == rlocator->spcOid && map_entry.relNumber == rlocator->relNumber)
597585
{
598586
TDEMapEntry empty_map_entry = {
599587
.flags = MAP_ENTRY_EMPTY,
@@ -616,7 +604,7 @@ pg_tde_delete_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t
616604

617605
/*
618606
* Called when transaction is being completed; either committed or aborted.
619-
* By default, when a transaction creates an entry, we mark it as MAP_ENTRY_VALID.
607+
* By default, when a transaction creates an entry, we mark it with the type.
620608
* Only during the abort phase of the transaction that we are proceed on with
621609
* marking the entry as MAP_ENTRY_FREE. This optimistic strategy that assumes
622610
* that transaction will commit more often then getting aborted avoids
@@ -712,22 +700,15 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
712700
while (1)
713701
{
714702
InternalKey *rel_key_data;
715-
off_t old_prev_pos,
716-
new_prev_pos;
703+
off_t new_prev_pos;
717704
TDEMapEntry read_map_entry,
718705
write_map_entry;
719706
RelFileLocator rloc;
720-
bool found;
721-
722-
old_prev_pos = old_curr_pos;
723-
found = pg_tde_read_one_map_entry(old_fd, NULL, MAP_ENTRY_VALID, &read_map_entry, &old_curr_pos);
724707

725-
/* We either reach EOF */
726-
if (old_prev_pos == old_curr_pos)
708+
if (!pg_tde_read_one_map_entry(old_fd, &read_map_entry, &old_curr_pos))
727709
break;
728710

729-
/* We didn't find a valid entry */
730-
if (found == false)
711+
if (read_map_entry.flags == MAP_ENTRY_EMPTY)
731712
continue;
732713

733714
rloc.spcOid = read_map_entry.spcOid;
@@ -975,8 +956,9 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type)
975956
}
976957

977958
/*
978-
* Returns the index of the read map if we find a valid match; e.g. flags is set to
979-
* MAP_ENTRY_VALID and the relNumber and spcOid matches the one provided in rlocator.
959+
* Returns the entry of the map if we find a valid match; e.g. flags is not
960+
* set to MAP_ENTRY_EMPTY and the relNumber and spcOid matches the one
961+
* provided in rlocator.
980962
*/
981963
static TDEMapEntry *
982964
pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_map_path)
@@ -985,30 +967,20 @@ pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_
985967
TDEMapEntry *map_entry = palloc_object(TDEMapEntry);
986968
off_t curr_pos = 0;
987969

970+
Assert(rlocator != NULL);
971+
988972
map_fd = pg_tde_open_file_read(db_map_path, &curr_pos);
989973

990-
/*
991-
* Read until we find an empty slot. Otherwise, read until end. This seems
992-
* to be less frequent than vacuum. So let's keep this function here
993-
* rather than overloading the vacuum process.
994-
*/
995974
while (1)
996975
{
997-
bool found;
998-
off_t prev_pos = curr_pos;
999-
1000-
found = pg_tde_read_one_map_entry(map_fd, rlocator, key_type, map_entry, &curr_pos);
1001-
1002-
/* We've reached EOF */
1003-
if (curr_pos == prev_pos)
976+
if (!pg_tde_read_one_map_entry(map_fd, map_entry, &curr_pos))
1004977
{
1005978
close(map_fd);
1006979
pfree(map_entry);
1007980
return NULL;
1008981
}
1009982

1010-
/* We found a valid entry for the relation */
1011-
if (found)
983+
if ((map_entry->flags & key_type) && map_entry->spcOid == rlocator->spcOid && map_entry->relNumber == rlocator->relNumber)
1012984
{
1013985
close(map_fd);
1014986
return map_entry;
@@ -1118,26 +1090,17 @@ pg_tde_file_header_read(const char *tde_filename, int fd, TDEFileHeader *fheader
11181090

11191091

11201092
/*
1121-
* Returns true if a valid map entry if found. Otherwise, it only increments
1122-
* the offset and returns false. If the same offset value is set, it indicates
1123-
* to the caller that nothing was read.
1124-
*
1125-
* If a non-NULL rlocator is provided, the function compares the read value
1126-
* against the relNumber of rlocator. It sets found accordingly.
1127-
*
1128-
* The caller is reponsible for identifying that we have reached EOF by
1129-
* comparing old and new value of the offset.
1093+
* Returns true if a map entry if found or false if we have reached the end of
1094+
* the file.
11301095
*/
11311096
static bool
1132-
pg_tde_read_one_map_entry(int map_file, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset)
1097+
pg_tde_read_one_map_entry(int map_file, TDEMapEntry *map_entry, off_t *offset)
11331098
{
1134-
bool found;
11351099
off_t bytes_read = 0;
11361100

11371101
Assert(map_entry);
11381102
Assert(offset);
11391103

1140-
/* Read the entry at the given offset */
11411104
bytes_read = pg_pread(map_file, map_entry, MAP_ENTRY_SIZE, *offset);
11421105

11431106
/* We've reached the end of the file. */
@@ -1146,14 +1109,7 @@ pg_tde_read_one_map_entry(int map_file, const RelFileLocator *rlocator, int flag
11461109

11471110
*offset += bytes_read;
11481111

1149-
/* We found a valid entry */
1150-
found = map_entry->flags & flags;
1151-
1152-
/* If a valid rlocator is provided, let's compare and set found value */
1153-
if (rlocator != NULL)
1154-
found &= map_entry->spcOid == rlocator->spcOid && map_entry->relNumber == rlocator->relNumber;
1155-
1156-
return found;
1112+
return true;
11571113
}
11581114

11591115
/*

contrib/pg_tde/src/include/access/pg_tde_tdemap.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#define TDE_KEY_TYPE_GLOBAL 0x04
2020
#define TDE_KEY_TYPE_WAL_UNENCRYPTED 0x08
2121
#define TDE_KEY_TYPE_WAL_ENCRYPTED 0x10
22-
#define MAP_ENTRY_VALID (TDE_KEY_TYPE_SMGR | TDE_KEY_TYPE_GLOBAL)
2322

2423
#define INTERNAL_KEY_LEN 16
2524
#define INTERNAL_KEY_IV_LEN 16

0 commit comments

Comments
 (0)