chore: thread context through to SendCustomMessage
What changed, and why it matters
This change fixes a minor responsiveness bug in LND's 'SendCustomMessage' RPC. Previously, if a caller cancelled the request, the server would still keep waiting until the peer became active, disconnected, or the whole server shut down. Now the cancellation signal is passed through and the call returns immediately when cancelled. It is a cleanup/quality improvement rather than a clear security vulnerability.
Treat as a routine reliability improvement. No urgent security action is required. Reviewers may want to confirm that other RPC handlers similarly respect context cancellation while waiting on peer signals, and that cancelling here does not leave partial message state.
Security signals we found
Ignored request context could delay cancellation and tie up RPC/goroutine resources
Patch improves graceful cancellation for an RPC that interacts with a peer
No input validation, authentication bypass, memory corruption, or cryptographic weakness visible in diff
Evidence from the diff
The commit threads the gRPC context into server.SendCustomMessage and adds a ctx.Done() case to the select statement that waits for peer.ActiveSignal(), peer.QuitSignal(), or server quit. Before, the context parameter was ignored (named ‘_’), so callers that cancelled the RPC could hang until one of the other events occurred. The patch improves cancellation semantics and resource cleanup but does not by itself prevent any active attack.
Changed components
rpcserver.go: SendCustomMessage RPC handlerserver.go: server.SendCustomMessage peer-message dispatchInspect captured patch +8 / −5
diff --git a/rpcserver.go b/rpcserver.go
index fd67434..6038563 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -9251,7 +9251,7 @@ func (r *rpcServer) RegisterRPCMiddleware(
}
// SendCustomMessage sends a custom peer message.
-func (r *rpcServer) SendCustomMessage(_ context.Context,
+func (r *rpcServer) SendCustomMessage(ctx context.Context,
req *lnrpc.SendCustomMessageRequest) (*lnrpc.SendCustomMessageResponse,
error) {
@@ -9261,7 +9261,7 @@ func (r *rpcServer) SendCustomMessage(_ context.Context,
}
err = r.server.SendCustomMessage(
- peer, lnwire.MessageType(req.Type), req.Data,
+ ctx, peer, lnwire.MessageType(req.Type), req.Data,
)
switch {
case errors.Is(err, ErrPeerNotConnected):
diff --git a/server.go b/server.go
index b7d4f23..6149db0 100644
--- a/server.go
+++ b/server.go
@@ -5263,21 +5263,24 @@ func (s *server) applyChannelUpdate(update *lnwire.ChannelUpdate1,
// SendCustomMessage sends a custom message to the peer with the specified
// pubkey.
-func (s *server) SendCustomMessage(peerPub [33]byte, msgType lnwire.MessageType,
- data []byte) error {
+func (s *server) SendCustomMessage(ctx context.Context, peerPub [33]byte,
+ msgType lnwire.MessageType, data []byte) error {
peer, err := s.FindPeerByPubStr(string(peerPub[:]))
if err != nil {
return err
}
- // We'll wait until the peer is active.
+ // We'll wait until the peer is active, but also listen for
+ // cancellation.
select {
case <-peer.ActiveSignal():
case <-peer.QuitSignal():
return fmt.Errorf("peer %x disconnected", peerPub)
case <-s.quit:
return ErrServerShuttingDown
+ case <-ctx.Done():
+ return ctx.Err()
}
msg, err := lnwire.NewCustom(msgType, data)
Why this scored 25/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.