Skip to content

Fixes: #4673 dht: fix wrong free of borrowed pointer in init error path#4672

Open
ThalesBarretto wants to merge 1 commit into
gluster:develfrom
ThalesBarretto:thales_dht_fix_borrowed_ptr_free
Open

Fixes: #4673 dht: fix wrong free of borrowed pointer in init error path#4672
ThalesBarretto wants to merge 1 commit into
gluster:develfrom
ThalesBarretto:thales_dht_fix_borrowed_ptr_free

Conversation

@ThalesBarretto
Copy link
Copy Markdown
Contributor

@ThalesBarretto ThalesBarretto commented Apr 28, 2026

Fixes: #4673

dht_init() error path calls GF_FREE(conf->xattr_name) on a pointer that was
never heap-allocated. GF_OPTION_INIT("xattr-name", conf->xattr_name, str, err)
stores a borrowed pointer via the pass() conversion function
(libglusterfs/src/options.c:1314: *out = in) — it points either to
opt->default_value (a .rodata string literal "trusted.glusterfs.dht") or to
dict-internal storage from dict_get_str(). Neither is caller-owned.

When __gf_free() is called on this pointer, it subtracts GF_MEM_HEADER_SIZE
and interprets the preceding memory as a struct mem_header — reading garbage.
The GF_ASSERT on the magic field fires but continues (SIGCONT), leading to heap
metadata corruption.

dht_fini() correctly does not free this pointer. The four derived xattr names
(link_xattr_name, wild_xattr_name, mds_xattr_key, commithash_xattr_name)
are allocated via gf_asprintf and correctly freed in both paths — the asymmetry
between the borrowed base name and the owned derived names is what caused the bug.

The line was introduced in 76bc5d1 (2013, "dht: make DHT xattr names
configurable") when the xattr-name option was added for a tiering vision. That
commit added conf->xattr_name alongside two gf_asprintf'd derived names and
freed all three uniformly in the error block — not realizing GF_OPTION_INIT str
returns a borrowed pointer while gf_asprintf returns an owned one. The tiering
feature was later removed (2019–2020) but the option itself cannot be deleted
because dht_init calls GF_OPTION_INIT("xattr-name", ...) unconditionally —
removing it from dht_options[] would break volume startup.

Fix: delete the wrong GF_FREE. One-line change, no functional impact.

GF_OPTION_INIT("xattr-name", conf->xattr_name, str, err) stores a
borrowed pointer via pass() — either opt->default_value (.rodata) or
data->data from dict_get_str() (dict-internal). Neither is owned by
the caller. The err: block at dht-shared.c:841 calls GF_FREE on it,
which causes __gf_free to read a fake mem_header from unrelated memory
and corrupt heap state.

dht_fini() correctly omits this free. The derived names (link_xattr_name,
wild_xattr_name, mds_xattr_key, commithash_xattr_name) are owned via
gf_asprintf and correctly freed.

Introduced in 76bc5d1 (2013) when xattr-name configurability was
added for tiering. The error block freed all names uniformly, not
realizing GF_OPTION_INIT str borrows rather than allocates.

Signed-off-by: Thales Antunes de Oliveira Barretto <[email protected]>
#  xlators/cluster/dht/src/dht-shared.c | 1 -
#  1 file changed, 1 deletion(-)
@ThalesBarretto ThalesBarretto marked this pull request as ready for review April 28, 2026 19:05
@ThalesBarretto ThalesBarretto changed the title dht: fix wrong free of borrowed pointer in init error path Fixes: #4673 dht: fix wrong free of borrowed pointer in init error path Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dht: GF_FREE(conf->xattr_name) in init error path corrupts heap — pointer is borrowed from GF_OPTION_INIT

1 participant