common: explain why mlock() failed instead of a bare abort - #9438
Open
mattraydub wants to merge 1 commit into
Open
common: explain why mlock() failed instead of a bare abort#9438mattraydub wants to merge 1 commit into
mattraydub wants to merge 1 commit into
Conversation
Andezion
approved these changes
Aug 20, 2026
Andezion
left a comment
Collaborator
There was a problem hiding this comment.
This message only reaches stderr. Operators running lightningd under systemd typically only watch the cln log file, not raw stderr. Was routing this through status_failed/the log considered, or is matching the existing crashdump() convention intentional?
|
|
||
| void mlock_tal_memory(const tal_t *ptr) | ||
| { | ||
| if (sodium_mlock((void *)ptr, tal_bytelen(ptr)) != 0) |
Collaborator
There was a problem hiding this comment.
daemon_setup() already calls err_set_progname(argv0) (via common_setup) before mlock_tal_memory() can run. Did you consider using ccan warn()/warnx() instead of a hand-rolled fprintf + strerror, so the message gets the daemon-name prefix for free and matches the warnx() call in crashdump() that immediately follows it on the same failure path?
mlock_tal_memory() aborts when sodium_mlock() fails, with no output at all. The operator sees only "lightning_hsmd: FATAL SIGNAL 6" and has no indication of the cause. This is easy to hit. FreeBSD jails deny mlock(2) unless the jail has allow.mlock set, and containerized Linux deployments hit the same wall against RLIMIT_MEMLOCK. In both cases the failure is indistinguishable from a crash. Keep the abort -- falling back to unlocked memory would silently leave the secret in swappable pages -- but say what failed and how to grant the privilege. Changelog-Fixed: Report the cause when locking secret memory fails, instead of aborting with no diagnostic.
Andezion
force-pushed
the
mlock-failure-diagnostic
branch
from
August 20, 2026 10:24
77fc67b to
1f86c30
Compare
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.
mlock_tal_memory()aborts whensodium_mlock()fails, with no output at all:There is no fallback path and no message, so the operator sees only:
How I found it
A node running fine on 25.09 died on every start after upgrading past 25.12.
Nothing in the logs pointed anywhere useful —
lightningd: HSM sent unknown message typeis emitted, but that is a red herring, justlightningdmisreading an already-dead subdaemon. It took a debug build to get the real
abort site:
The cause was that FreeBSD jails deny
mlock(2)unless the jail hasallow.mlockset. Granting it fixes the node with no other change. Because25.09 and earlier did not lock the secret, the missing permission stays
invisible until the first upgrade past 25.12 — which makes it look like a
release regression rather than a configuration issue.
Containerized Linux deployments hit the same wall against
RLIMIT_MEMLOCKand fail exactly as opaquely.
Full write-up, including the confirmation that the stock package starts
normally once the privilege is granted:
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297253
What this changes
Only the diagnostic. The
abort()stays deliberately — falling back tounlocked memory would silently leave
hsm_secretin swappable pages, andthat is a security policy change that shouldn't ride along on a patch about
error messages. If you'd rather have an opt-out flag for environments that
can't grant the privilege, I'm happy to follow up separately.
New output on failure:
Checks
tools/check-includes.shpasses (stdio.h/string.hadded in thealphabetical position it expects)
-Wformat=2 -Werror(%zuagainsttal_bytelen()'ssize_t)