askrene: close files in child to isolate against bugs.
What changed, and why it matters
This change is a hardening fix in a Core Lightning plugin called askrene. When askrene spawns a child process to do heavy route-finding work, the child previously inherited all of the parent's open file descriptors (network sockets, pipes, files). If the child had a bug, it could accidentally write to or close those inherited descriptors, disrupting the plugin's connection to the main lightningd daemon. The patch makes the child close most inherited file descriptors (keeping only standard error) so a buggy child cannot interfere with the parent's communication channels.
Treat as a low-risk hardening improvement. No urgent action required. Review whether closing all FDs except stderr is sufficient and whether FD_CLOEXEC should be set on plugin sockets at creation for stronger isolation.
Security signals we found
file descriptor leak/isolation in forked child
defense-in-depth hardening
potential child process interference with parent daemon connection
no explicit vulnerability or exploit described
Evidence from the diff
In plugins/askrene/askrene.c, do_getroutes() forks a child process to run run_child(). Before exec, the child inherits the parent’s FDs, including the plugin’s JSON-RPC connection to lightningd and internal pipes. The patch adds a loop that closes FDs 0..min(logfds[1], replyfds[1]) except stderr (fd 2). This isolates the child from the parent’s file descriptors, reducing the blast radius of child bugs such as accidental writes/close on the lightningd connection or reply/log pipes. It is a defense-in-depth measure, not a fix for a known exploitable vulnerability.
Changed components
plugins/askrene/askrene.cdo_getroutes()child process spawned for route computationInspect captured patch +7 / −0
diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c
index a5709c12..c16aa650 100644
--- a/plugins/askrene/askrene.c
+++ b/plugins/askrene/askrene.c
@@ -653,6 +653,13 @@ static struct command_result *do_getroutes(struct command *cmd,
close(replyfds[0]);
set_child_log_fd(logfds[1]);
+ /* Make sure we don't stomp over plugin fds, even if we have a bug */
+ for (int i = 0; i < min_u64(logfds[1], replyfds[1]); i++) {
+ /* stderr is maintained */
+ if (i != 2)
+ close(i);
+ }
+
/* Does not return! */
run_child(askrene->gossmap,
layers,
Why this scored 34/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.