Skip to content

common/options: fix heap-use-after-free by using never-destroyed static#66895

Merged
tchaikov merged 1 commit intoceph:mainfrom
tchaikov:wip-common-options-fix-hea-use-after-free
Jan 13, 2026
Merged

common/options: fix heap-use-after-free by using never-destroyed static#66895
tchaikov merged 1 commit intoceph:mainfrom
tchaikov:wip-common-options-fix-hea-use-after-free

Conversation

@tchaikov
Copy link
Contributor

The config schema map was using string_view keys that pointed to the name field of Option objects stored in the global ceph_options vector. When the vector is destroyed during program exit, the Option objects are freed, but background threads (like BlueStore::MempoolThread) may still be accessing config options, causing use-after-free.

ASan reported:
  READ of size 19 at 0x503000047c80 thread T411
    #12 md_config_t::find_option(std::string_view) const config.cc:261
    #17 BlueStore::MempoolThread::entry() BlueStore.cc:5591

  0x503000047c80 is located 0 bytes inside of 20-byte region
  freed by thread T0 here:
    #7 Option::~Option() options.h:15
    #13 std::vector<Option>::~vector() stl_vector.h:730
    #14 __run_exit_handlers stdlib/exit.c:113

  previously allocated by thread T0 here:
    #7 Option::Option(Option const&) options.h:15
    #18 build_options() build_options.cc:44

Fix by converting ceph_options from a global variable to a function get_ceph_options() that returns a reference to a static pointer that is never destroyed. This ensures the Option objects remain valid for the lifetime of the program, even during exit when background threads may still be accessing them.

This preserves the memory efficiency of using string_view keys in the schema map while fixing the lifetime issue.

Contribution Guidelines

  • To sign and title your commits, please refer to Submitting Patches to Ceph.

  • If you are submitting a fix for a stable branch (e.g. "quincy"), please refer to Submitting Patches to Ceph - Backports for the proper workflow.

  • When filling out the below checklist, you may click boxes directly in the GitHub web UI. When entering or editing the entire PR message in the GitHub web UI editor, you may also select a checklist item by adding an x between the brackets: [x]. Spaces and capitalization matter when checking off items this way.

Checklist

  • Tracker (select at least one)
    • References tracker ticket
    • Very recent bug; references commit where it was introduced
    • New feature (ticket optional)
    • Doc update (no ticket needed)
    • Code cleanup (no ticket needed)
  • Component impact
    • Affects Dashboard, opened tracker ticket
    • Affects Orchestrator, opened tracker ticket
    • No impact that needs to be tracked
  • Documentation (select at least one)
    • Updates relevant documentation
    • No doc update is appropriate
  • Tests (select at least one)
Show available Jenkins commands

You must only issue one Jenkins command per-comment. Jenkins does not understand
comments with more than one command.

The config schema map was using string_view keys that pointed to the
name field of Option objects stored in the global ceph_options vector.
When the vector is destroyed during program exit, the Option objects
are freed, but background threads (like BlueStore::MempoolThread) may
still be accessing config options, causing use-after-free.

ASan reported:
  READ of size 19 at 0x503000047c80 thread T411
    #12 md_config_t::find_option(std::string_view) const config.cc:261
    ceph#17 BlueStore::MempoolThread::entry() BlueStore.cc:5591

  0x503000047c80 is located 0 bytes inside of 20-byte region
  freed by thread T0 here:
    #7 Option::~Option() options.h:15
    ceph#13 std::vector<Option>::~vector() stl_vector.h:730
    ceph#14 __run_exit_handlers stdlib/exit.c:113

  previously allocated by thread T0 here:
    #7 Option::Option(Option const&) options.h:15
    ceph#18 build_options() build_options.cc:44

Fix by converting ceph_options from a global variable to a function
get_ceph_options() that returns a reference to a static pointer that
is never destroyed. This ensures the Option objects remain valid for
the lifetime of the program, even during exit when background threads
may still be accessing them.

This preserves the memory efficiency of using string_view keys in the
schema map while fixing the lifetime issue.

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
@ronen-fr
Copy link
Contributor

Thanks for maintaining the string_view...

@tchaikov tchaikov merged commit 98620c2 into ceph:main Jan 13, 2026
13 of 14 checks passed
@tchaikov tchaikov deleted the wip-common-options-fix-hea-use-after-free branch January 13, 2026 06:07
@xxhdx1985126
Copy link
Contributor

Um, seems that, with this PR, we meet the issue: https://tracker.ceph.com/issues/74481

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants