From c954830fa93142a66eb29e4bbb089b88e86a7d6b Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 29 Oct 2025 21:25:42 +0100 Subject: [PATCH] core/service: only pass socket fds to control processes If socket is used as stdio, we'd currently imply EXEC_PASS_FDS and dump the whole set of fds to the control processes. This is pretty much unexpected and unnecessary though, instead let's pass only the socket fds. Yes, this is a compat break, but a relatively minor one I'd argue. And we can always revisit things if users do complain. --- src/core/execute.c | 2 +- src/core/service.c | 28 ++++++++++++++++++---------- src/core/socket.c | 1 - 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index baadad93771..5b01758733a 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -486,8 +486,8 @@ int exec_spawn( assert(command); assert(context); assert(params); - assert(!params->fds || FLAGS_SET(params->flags, EXEC_PASS_FDS)); assert(params->fds || (params->n_socket_fds + params->n_stashed_fds == 0 && !params->fd_names)); + assert(params->n_stashed_fds == 0 || FLAGS_SET(params->flags, EXEC_PASS_FDS)); assert(!params->files_env); /* We fill this field, ensure it comes NULL-initialized to us */ assert(ret); diff --git a/src/core/service.c b/src/core/service.c index 46aabdfe42c..e1cc618fc4d 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1462,7 +1462,6 @@ static int service_collect_fds( assert(fds); assert(fd_names); assert(n_socket_fds); - assert(n_stashed_fds); if (s->socket_fd >= 0) { Socket *sock = ASSERT_PTR(SOCKET(UNIT_DEREF(s->accept_socket))); @@ -1509,7 +1508,7 @@ static int service_collect_fds( } } - if (s->n_fd_store + s->n_extra_fds > 0) { + if (n_stashed_fds && s->n_fd_store + s->n_extra_fds > 0) { int *t = reallocarray(rfds, rn_socket_fds + s->n_fd_store + s->n_extra_fds, sizeof(int)); if (!t) return -ENOMEM; @@ -1546,7 +1545,8 @@ static int service_collect_fds( *fds = TAKE_PTR(rfds); *fd_names = TAKE_PTR(rfd_names); *n_socket_fds = rn_socket_fds; - *n_stashed_fds = s->n_fd_store + s->n_extra_fds; + if (n_stashed_fds) + *n_stashed_fds = s->n_fd_store + s->n_extra_fds; return 0; } @@ -1730,11 +1730,7 @@ static int service_spawn_internal( exec_params.flags &= ~EXEC_APPLY_CHROOT; } - if (FLAGS_SET(exec_params.flags, EXEC_PASS_FDS) || - s->exec_context.std_input == EXEC_INPUT_SOCKET || - s->exec_context.std_output == EXEC_OUTPUT_SOCKET || - s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { - + if (FLAGS_SET(exec_params.flags, EXEC_PASS_FDS)) { r = service_collect_fds(s, &exec_params.fds, &exec_params.fd_names, @@ -1743,11 +1739,23 @@ static int service_spawn_internal( if (r < 0) return r; + log_unit_debug(UNIT(s), "Passing %zu fds to service", exec_params.n_socket_fds + exec_params.n_stashed_fds); + exec_params.open_files = s->open_files; - exec_params.flags |= EXEC_PASS_FDS; + } else if (s->exec_context.std_input == EXEC_INPUT_SOCKET || + s->exec_context.std_output == EXEC_OUTPUT_SOCKET || + s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { - log_unit_debug(UNIT(s), "Passing %zu fds to service", exec_params.n_socket_fds + exec_params.n_stashed_fds); + r = service_collect_fds(s, + &exec_params.fds, + &exec_params.fd_names, + &exec_params.n_socket_fds, + /* n_stashed_fds = */ NULL); + if (r < 0) + return r; + + log_unit_debug(UNIT(s), "Passing %zu sockets to service", exec_params.n_socket_fds); } if (!FLAGS_SET(exec_params.flags, EXEC_IS_CONTROL) && s->type == SERVICE_EXEC) { diff --git a/src/core/socket.c b/src/core/socket.c index 1ae3affd0df..c946d257246 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2001,7 +2001,6 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) { if (r < 0) return r; - exec_params.flags |= EXEC_PASS_FDS; exec_params.fds = TAKE_PTR(fds); exec_params.fd_names = TAKE_PTR(fd_names); exec_params.n_socket_fds = n_fds; -- 2.47.3