[17151] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

[krbdev.mit.edu #9276] macOS API ccache crashes a child forked after

daemon@ATHENA.MIT.EDU (Douglas Eichelberger via RT)
Sat Oct 31 17:47:43 2026

From: "Douglas Eichelberger via RT" <rt-comment@krbdev.mit.edu>
In-Reply-To: <CALjFiD6PBCcq3yOdznUst+pjhRuyf-EcEGq9KC9F-S7wbu79AQ@mail.gmail.com>
Message-ID: <rt-4.4.3-2-1966774-1793483255-1195.9276-4-0@mit.edu>
To: "AdminCc of krbdev.mit.edu Ticket #9276":;
Date: Sat, 31 Oct 2026 17:47:35 -0400
MIME-Version: 1.0
Reply-To: rt-comment@krbdev.mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: krb5-bugs-bounces@mit.edu


Sat Oct 31 17:47:35 2026: Request 9276 was acted upon.
 Transaction: Ticket created by d@eic.email
       Queue: krb5
     Subject: macOS API ccache crashes a child forked after the parent used it
       Owner: Nobody
  Requestors: d@eic.email
      Status: new
 Ticket <URL: https://krbdev.mit.edu/rt/Ticket/Display.html?id=9276 >


Hello,

On macOS, the API ccache can crash a child process forked after the
parent used it. I've opened a pull request with a proposed fix:
https://github.com/krb5/krb5/pull/1558

Versions: krb5 master (82a4224f0) and 1.22.2, built natively on
macOS 27.0.1 (arm64) with the default API: ccache. The krb5 1.22.x
that the Ruby pg gem's macOS binaries link statically behaves the same.

libpq calls gss_acquire_cred(GSS_C_NO_NAME, ...) on each TCP connection
attempt when gssencmode=prefer, its default. A Ruby process that
connects to PostgreSQL, forks, and connects again is killed by SIGSEGV
in the child:

  gss_acquire_cred > gss_acquire_cred_from > gss_add_cred_from >
  krb5_gss_acquire_cred_from > acquire_cred_from > acquire_cred_context >
  acquire_init_cred > krb5_cccol_have_content > krb5_cccol_cursor_next >
  api_macos_ptcursor_next > get_primary_name > xpc_connection_resume >
  _xpc_connection_activate_if_needed > os_log_type_enabled >
  _os_log_preferences_refresh > SIGSEGV

The crash reports also record "CoreFoundation: *** multi-threaded
process forked ***" and "libsystem_c.dylib: crashed on child side of
fork pre-exec".

Reproduction, with the pg gem built against a libpq that links this
krb5. No server is needed: port 1 is closed, and libpq probes for
credentials before it connects.

  require "pg"
  attempt = -> { PG.connect(host: "127.0.0.1", port: 1, connect_timeout: 2)
rescue PG::ConnectionBad }
  attempt.call
  pid = fork { attempt.call; exit!(0) }
  Process.wait(pid)
  p $?.termsig   # 11

I couldn't reproduce it with this krb5 in a plain C program that calls
gss_acquire_cred() before and after fork(). It needs some of the state
a Ruby process sets up: Ruby links CoreFoundation and starts a thread
in the child. Apple's GSS.framework does crash in the plain C case.

The proposed change records the pid of the first API ccache use. In a
child forked after that, the API collection reads as empty, resolving
or opening a cache fails with KRB5_FCC_NOFILE, and CCAPI objects
inherited from the parent are left unreleased, so the child never calls
the CCAPI framework or XPC. With it, the reproduction above exits
normally on master and on 1.22.2, and make check in
src/lib/krb5/ccache passes.

Workarounds until a fix ships: KRB5CCNAME=FILE:<path>, or turning off
GSSAPI encryption negotiation in the client (gssencmode=disable for
libpq).

Related reports:
https://github.com/ged/ruby-pg/issues/663
https://github.com/ged/ruby-pg/issues/311
https://www.postgresql.org/message-id/flat/93f7379b-2e2f-db0c-980e-07ebd5de92ff%40crunchydata.com
(PostgreSQL bug #16041, the same crash through Apple's Heimdal)

Thanks,
Doug Eichelberger

_______________________________________________
krb5-bugs mailing list
krb5-bugs@mit.edu
https://mailman.mit.edu/mailman/listinfo/krb5-bugs

home help back first fref pref prev next nref lref last post