Skip to content

Commit 5c06ab6

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 a6f774e commit 5c06ab6

File tree

2 files changed

+24
-69
lines changed

2 files changed

+24
-69
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

+24-68
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static TDEMapEntry *pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32
113113
static InternalKey *tde_decrypt_rel_key(TDEPrincipalKey *principal_key, TDEMapEntry *map_entry);
114114
static int pg_tde_open_file_basic(const char *tde_filename, int fileFlags, bool ignore_missing);
115115
static void pg_tde_file_header_read(const char *tde_filename, int fd, TDEFileHeader *fheader, off_t *bytes_read);
116-
static bool pg_tde_read_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset);
116+
static bool pg_tde_read_one_map_entry(int fd, TDEMapEntry *map_entry, off_t *offset);
117117
static void pg_tde_read_one_map_entry2(int keydata_fd, int32 key_index, TDEMapEntry *map_entry, Oid databaseId);
118118
static int pg_tde_open_file_read(const char *tde_filename, off_t *curr_pos);
119119
static InternalKey *pg_tde_get_key_from_cache(const RelFileLocator *rlocator, uint32 key_type);
@@ -447,16 +447,12 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, InternalKey *rel_key_
447447
while (1)
448448
{
449449
TDEMapEntry read_map_entry;
450-
bool found;
451450

452451
prev_pos = curr_pos;
453-
found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &read_map_entry, &curr_pos);
452+
if (!pg_tde_read_one_map_entry(map_fd, &read_map_entry, &curr_pos))
453+
break;
454454

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

@@ -517,16 +513,12 @@ pg_tde_write_key_map_entry_redo(const TDEMapEntry *write_map_entry, TDESignedPri
517513
while (1)
518514
{
519515
TDEMapEntry read_map_entry;
520-
bool found;
521516

522517
prev_pos = curr_pos;
523-
found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &read_map_entry, &curr_pos);
518+
if (!pg_tde_read_one_map_entry(map_fd, &read_map_entry, &curr_pos))
519+
break;
524520

525-
/*
526-
* We either reach EOF or found an empty slot in the middle of the
527-
* file
528-
*/
529-
if (prev_pos == curr_pos || found)
521+
if (read_map_entry.flags == MAP_ENTRY_EMPTY)
530522
break;
531523
}
532524

@@ -567,17 +559,13 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator)
567559

568560
while (1)
569561
{
570-
TDEMapEntry read_map_entry;
562+
TDEMapEntry map_entry;
571563
off_t prev_pos = curr_pos;
572-
bool found;
573-
574-
found = pg_tde_read_one_map_entry(map_fd, rlocator, MAP_ENTRY_VALID, &read_map_entry, &curr_pos);
575564

576-
/* We've reached EOF */
577-
if (curr_pos == prev_pos)
565+
if (!pg_tde_read_one_map_entry(map_fd, &map_entry, &curr_pos))
578566
break;
579567

580-
if (found)
568+
if (map_entry.flags != MAP_ENTRY_EMPTY && map_entry.spcOid == rlocator->spcOid && map_entry.relNumber == rlocator->relNumber)
581569
{
582570
TDEMapEntry empty_map_entry = {
583571
.flags = MAP_ENTRY_EMPTY,
@@ -653,22 +641,15 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
653641
while (1)
654642
{
655643
InternalKey *rel_key_data;
656-
off_t old_prev_pos,
657-
new_prev_pos;
644+
off_t new_prev_pos;
658645
TDEMapEntry read_map_entry,
659646
write_map_entry;
660647
RelFileLocator rloc;
661-
bool found;
662648

663-
old_prev_pos = old_curr_pos;
664-
found = pg_tde_read_one_map_entry(old_fd, NULL, MAP_ENTRY_VALID, &read_map_entry, &old_curr_pos);
665-
666-
/* We either reach EOF */
667-
if (old_prev_pos == old_curr_pos)
649+
if (!pg_tde_read_one_map_entry(old_fd, &read_map_entry, &old_curr_pos))
668650
break;
669651

670-
/* We didn't find a valid entry */
671-
if (found == false)
652+
if (read_map_entry.flags == MAP_ENTRY_EMPTY)
672653
continue;
673654

674655
rloc.spcOid = read_map_entry.spcOid;
@@ -916,8 +897,9 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type)
916897
}
917898

918899
/*
919-
* Returns the index of the read map if we find a valid match; e.g. flags is set to
920-
* MAP_ENTRY_VALID and the relNumber and spcOid matches the one provided in rlocator.
900+
* Returns the entry of the map if we find a valid match; e.g. flags is not
901+
* set to MAP_ENTRY_EMPTY and the relNumber and spcOid matches the one
902+
* provided in rlocator.
921903
*/
922904
static TDEMapEntry *
923905
pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_map_path)
@@ -926,30 +908,20 @@ pg_tde_find_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_
926908
TDEMapEntry *map_entry = palloc_object(TDEMapEntry);
927909
off_t curr_pos = 0;
928910

911+
Assert(rlocator != NULL);
912+
929913
map_fd = pg_tde_open_file_read(db_map_path, &curr_pos);
930914

931-
/*
932-
* Read until we find an empty slot. Otherwise, read until end. This seems
933-
* to be less frequent than vacuum. So let's keep this function here
934-
* rather than overloading the vacuum process.
935-
*/
936915
while (1)
937916
{
938-
bool found;
939-
off_t prev_pos = curr_pos;
940-
941-
found = pg_tde_read_one_map_entry(map_fd, rlocator, key_type, map_entry, &curr_pos);
942-
943-
/* We've reached EOF */
944-
if (curr_pos == prev_pos)
917+
if (!pg_tde_read_one_map_entry(map_fd, map_entry, &curr_pos))
945918
{
946919
close(map_fd);
947920
pfree(map_entry);
948921
return NULL;
949922
}
950923

951-
/* We found a valid entry for the relation */
952-
if (found)
924+
if ((map_entry->flags & key_type) && map_entry->spcOid == rlocator->spcOid && map_entry->relNumber == rlocator->relNumber)
953925
{
954926
close(map_fd);
955927
return map_entry;
@@ -1059,26 +1031,17 @@ pg_tde_file_header_read(const char *tde_filename, int fd, TDEFileHeader *fheader
10591031

10601032

10611033
/*
1062-
* Returns true if a valid map entry if found. Otherwise, it only increments
1063-
* the offset and returns false. If the same offset value is set, it indicates
1064-
* to the caller that nothing was read.
1065-
*
1066-
* If a non-NULL rlocator is provided, the function compares the read value
1067-
* against the relNumber of rlocator. It sets found accordingly.
1068-
*
1069-
* The caller is reponsible for identifying that we have reached EOF by
1070-
* comparing old and new value of the offset.
1034+
* Returns true if a map entry if found or false if we have reached the end of
1035+
* the file.
10711036
*/
10721037
static bool
1073-
pg_tde_read_one_map_entry(int map_file, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset)
1038+
pg_tde_read_one_map_entry(int map_file, TDEMapEntry *map_entry, off_t *offset)
10741039
{
1075-
bool found;
10761040
off_t bytes_read = 0;
10771041

10781042
Assert(map_entry);
10791043
Assert(offset);
10801044

1081-
/* Read the entry at the given offset */
10821045
bytes_read = pg_pread(map_file, map_entry, MAP_ENTRY_SIZE, *offset);
10831046

10841047
/* We've reached the end of the file. */
@@ -1087,14 +1050,7 @@ pg_tde_read_one_map_entry(int map_file, const RelFileLocator *rlocator, int flag
10871050

10881051
*offset += bytes_read;
10891052

1090-
/* We found a valid entry */
1091-
found = map_entry->flags & flags;
1092-
1093-
/* If a valid rlocator is provided, let's compare and set found value */
1094-
if (rlocator != NULL)
1095-
found &= map_entry->spcOid == rlocator->spcOid && map_entry->relNumber == rlocator->relNumber;
1096-
1097-
return found;
1053+
return true;
10981054
}
10991055

11001056
/*

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

-1
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)