Fixed RELCACHE_FORCE_RELEASE related use-after-free bugs#8477
Merged
onurctirtir merged 2 commits intocitusdata:mainfrom Feb 16, 2026
Merged
Fixed RELCACHE_FORCE_RELEASE related use-after-free bugs#8477onurctirtir merged 2 commits intocitusdata:mainfrom
onurctirtir merged 2 commits intocitusdata:mainfrom
Conversation
Contributor
Author
@microsoft-github-policy-service agree |
onurctirtir
approved these changes
Feb 16, 2026
Member
onurctirtir
left a comment
There was a problem hiding this comment.
Thanks for the PR, all code changes make sense to me!
Contributor
Author
|
Glad I could be of help :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BUG REPORT FOR PROPOSED CHANGES
Summary
Three use-after-free bugs exist in Citus where
Relationstruct members are accessed afterrelation_close()ortable_close()has been called. Under normal operation these may gounnoticed because the relcache entry often remains cached in memory, but they are real memory
safety violations that cause segfaults and incorrect behavior when PostgreSQL is built
with
RELCACHE_FORCE_RELEASE(which forces immediate eviction of relcache entries on close).Versions
mainbranch at commite1875b93("Add changelog entry for Citus v14.0.0")REL_18_STABLE(18.2)Note
The following bug sections assume that the extension is installed. The steps for
reproducing the bug are always performed on A. vanilla PostgreSQL and Citus
compiled from scratch without any special compile flags, B. with Postgres compiled
with DRELCACHE_FORCE_RELEASE and Citus compiled with bugs, and C. with Postgres
compiled DRELCACHE_FORCE_RELEASE and Citus compiled with the bug fixes.
Additionally the flags
-O0 -gand the configure options--enable-debugand--enable-casserthave been used for Postgres.Bug 1:
index.c:200—relation->rd_idused aftertable_close()The relation is closed at line 176, but
relation->rd_idis read at line 200 whencreateIndexStatement->idxname == NULLand the index has expressions. At this pointthe
Relationstruct may have been freed.Reproduction
Observed behavior
A. Vanilla Postgres:
No error:
B. With RELCACHE_FORCE_RELEASE:
Random OID is used for relation lookup:
2139062143 = 0x7F7F7F7F— the cassert wipe pattern, confirming the read is from freed memory.C. With RELCACHE_FORCE_RELEASE and the bug fix:
No error:
Bug 2:
alter_table.c:1366—relation->rd_rel->relamused afterrelation_close()The relation is closed at line 1357, but
relation->rd_rel->relamis dereferenced atlines 1366 and 1370. This involves a double dereference (
relation->rd_relthen->relam),making it more dangerous -> if either
relationorrd_relitself point to freed memory, the dereferencecan segfault.
Reproduction
Observed behavior
A. Vanilla Postgres:
No error:
B. With RELCACHE_FORCE_RELEASE:
The server process crashed:
The server process output confirms the segmentation fault:
C. With RELCACHE_FORCE_RELEASE and the bug fix:
No error:
Bug 3:
multi_partitioning_utils.c:342—RelationGetRelationName(relation)used afterrelation_close()The relation is closed at line 338, but
RelationGetRelationName(relation)is called atline 342 inside the
ereport. The macro expands toNameStr((relation)->rd_rel->relname),which involves a double dereference through
rd_rel-> the same dangerous pattern as Bug 2.Reproduction
Observed behavior
A. Vanilla Postgres:
An error is thrown:
B. With RELCACHE_FORCE_RELEASE:
The server process crashed:
The server process output confirms the segmentation fault:
C. With RELCACHE_FORCE_RELEASE and the bug fix:
An error is thrown:
Impact
it errors out; in the worst case it could silently create an index on the wrong relation.
and requiring server recovery.
fix_partition_shard_index_names()is called on a non-partitioned distributed table,terminating the client connection.
I hope this makes my changes transparent. If you need any further information, just let me know.
Kind regards
Bernd