Skip to content

Fix segfault in fts_solr#276

Open
nick-oconnor wants to merge 1 commit intodovecot:mainfrom
nick-oconnor:main
Open

Fix segfault in fts_solr#276
nick-oconnor wants to merge 1 commit intodovecot:mainfrom
nick-oconnor:main

Conversation

@nick-oconnor
Copy link
Copy Markdown

@nick-oconnor nick-oconnor commented Apr 1, 2026

Dovecot 2.4.3 crashes with SIGSEGV in indexer-worker and lmtp during FTS Solr indexing. The crash is a use-after-free triggered when the HTTP client does a DNS lookup for the Solr host.

Environment

  • Dovecot 2.4.3 (Alpine 3.23 / musl)
  • Linux x86_64
  • Filesystem: maildir on ZFS
  • Solr 10.0.0
  • fts_solr plugin with DNS-based Solr URL

dovecot -n:

# 2.4.3 (e278b1e09b): /etc/dovecot/dovecot.conf
# Pigeonhole version 2.4.3 (0bf9ee48)
# OS: Linux 6.12.74+deb13+1-amd64 x86_64
dovecot_config_version = 2.4.0
auth_mechanisms = oauthbearer xoauth2
dovecot_storage_version = 2.4.0
fts_autoindex = yes
fts_search_add_missing = yes
mail_always_cache_fields = date.save
mail_driver = maildir
mail_plugins {
  fts = yes
  fts_solr = yes
}
protocols = imap lmtp sieve
ssl = required
fts solr {
  url = http://solr.example.com/solr/dovecot
}

(LDAP userdb/passdb, pigeonhole sieve, imapsieve for spam learning, and oauth2 passdb omitted)

How to reproduce

The crash occurs in the indexer-worker when processing multiple user mailboxes sequentially for FTS indexing, using a DNS hostname for the Solr URL.

Steps:

  1. Configure fts_solr with a DNS-based URL (not an IP address)
  2. Have the indexer-worker process mailboxes for more than one user (e.g. fts_autoindex = yes with multiple users, or manual doveadm index -A)
  3. The first user session completes successfully. On the second user session, the indexer-worker crashes with SIGSEGV during the DNS lookup for the Solr host.

Reproduces reliably on musl (Alpine) due to aggressive memory reuse. Likely also affects glibc but may not crash immediately due to delayed reuse of freed memory.

Root cause

The solr_http_client singleton outlives the user session that created it. Its event chain holds a ref on the mail_storage_service_user event, keeping it alive after the user is freed. The SETTINGS_EVENT_INSTANCE on that event still points to the already-freed settings_instance. On the next user session, dns_lookup() walks the stale event chain and dereferences the dangling pointer in settings_instance_get().

Stack trace (from core dump, debug build with musl-dbg):

#0  strlen(s=0x415641d189485741)              — SIGSEGV, freed/reused memory
#1  p_strdup()                                  strfuncs.c:56
#2  event_add_str(key="protocol", value=...)    lib-event.c:1099
#3  settings_instance_get()                     settings.c:2521
#4  settings_get_real()                         settings.c:2706
#5  settings_get_full()                         settings.c:2915
#6  settings_get(dns_client_setting_parser_info) settings.c:2976
#7  dns_client_init()                           dns-lookup.c:465
#8  dns_client_init_handle_failure()            dns-lookup.c:317
#9  dns_lookup("solr.example.com")              dns-lookup.c:337
#10 http_client_host_shared_lookup()            http-client-host.c:166
#11 http_client_host_shared_refresh()           http-client-host.c:195
#12-#19 http_client queue/host/request submit chain
#20 http_client_request_continue_payload()      http-client-request.c:1170
#21 http_client_request_send_payload()          http-client-request.c:1261
#22 solr_connection_post_more()                 solr-connection.c:269

Proposed fix

Destroy solr_http_client in solr_connection_deinit() so it is recreated with a fresh event chain on the next user session.

I've been running for few days with the patch applied. FTS indexing across multiple user sessions completes without crashes using a DNS-based Solr URL.

I sent this to the mailing list but this seems to be the place to submit patches.

Destroy solr_http_client in solr_connection_deinit() so it is recreated with a fresh event chain on the next user session.

The solr_http_client singleton outlives the user session that created it. Its event chain holds a ref on the mail_storage_service_user event, keeping it alive after the user is freed. The SETTINGS_EVENT_INSTANCE on that event still points to the already-freed settings_instance. On the next user session, dns_lookup() walks the stale event chain and dereferences the dangling pointer in settings_instance_get() resulting in a segfault.
@nick-oconnor nick-oconnor changed the title Fix SIGSEGV in fts_solr Fix segfault in fts_solr Apr 2, 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.

1 participant