ecdh_hsmd: ensure HSM fd is blocking on setup
What changed, and why it matters
This commit fixes a bug where a special internal communication channel (file descriptor) used by Core Lightning could accidentally be left in non-blocking mode on macOS under heavy load. When that happened, a part of the program expecting a blocking read would get an unexpected 'try again' error and crash with 'No hsmd ECDH response.' The fix explicitly forces the channel to blocking mode when it is set up, matching a safety pattern already used elsewhere in the codebase. It is a reliability fix rather than a security vulnerability in the usual attacker-vs-system sense.
Treat as a stability/reliability fix. Apply the patch and backport to maintained branches, especially for macOS deployments. No immediate incident-response action is required unless node operators on macOS are experiencing intermittent 'No hsmd ECDH response' crashes, in which case upgrading will resolve it.
Security signals we found
Crash/DoS condition in connectd/channeld due to unexpected EAGAIN on synchronous HSM read
Inherited O_NONBLOCK on SCM_RIGHTS-passed socketpair fd on macOS
Defensive hardening: explicit blocking-mode enforcement on setup
Pattern consistency with existing subd.c read_fds() hardening
Evidence from the diff
In common/ecdh_hsmd.c, ecdh_hsmd_setup() now calls io_fd_block(hsm_fd, true) on the HSM file descriptor received over SCM_RIGHTS. On macOS, socketpair file descriptors passed via SCM_RIGHTS can inherit O_NONBLOCK from the sender’s io_new_conn in hsmd’s pass_client_hsmfd. That caused wire_sync_read() to return NULL with EAGAIN, which connectd/channeld treated as fatal (‘No hsmd ECDH response’). The patch mirrors the existing defensive pattern in lightningd/subd.c:read_fds() and prevents the intermittent crash.
Changed components
common/ecdh_hsmd.cconnectdchanneldhsmdmacOS-specific behavior of SCM_RIGHTS/socketpairInspect captured patch +3 / −0
diff --git a/common/ecdh_hsmd.c b/common/ecdh_hsmd.c
index 8afa4581..68be5984 100644
--- a/common/ecdh_hsmd.c
+++ b/common/ecdh_hsmd.c
@@ -1,5 +1,6 @@
#include "config.h"
#include <assert.h>
+#include <ccan/io/io.h>
#include <common/ecdh.h>
#include <common/ecdh_hsmd.h>
#include <common/utils.h>
@@ -33,4 +34,6 @@ void ecdh_hsmd_setup(int hsm_fd,
{
stashed_hsm_fd = hsm_fd;
stashed_failed = failed;
+ /* Like read_fds in subd.c: don't trust sender's O_NONBLOCK state (issue #9060). */
+ io_fd_block(hsm_fd, true);
}
Why this scored 47/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.