diff mbox series

libxl: Don't leak self pipes

Message ID 20220524163152.19948-1-jandryuk@gmail.com (mailing list archive)
State New, archived
Headers show
Series libxl: Don't leak self pipes | expand

Commit Message

Jason Andryuk May 24, 2022, 4:31 p.m. UTC
libxl is leaking self pipes to child processes.  These can be seen when
running with env var _LIBXL_DEBUG_EXEC_FDS=1:

libxl: debug: libxl_aoutils.c:593:libxl__async_exec_start: forking to execute: /etc/xen/scripts/vif-bridge online
[Detaching after fork from child process 5099]
libxl: execing /etc/xen/scripts/vif-bridge: fd 4 is open to pipe:[46805] with flags 0
libxl: execing /etc/xen/scripts/vif-bridge: fd 13 is open to pipe:[46807] with flags 0
libxl: execing /etc/xen/scripts/vif-bridge: fd 14 is open to pipe:[46807] with flags 0
libxl: execing /etc/xen/scripts/vif-bridge: fd 19 is open to pipe:[48570] with flags 0
libxl: execing /etc/xen/scripts/vif-bridge: fd 20 is open to pipe:[48570] with flags 0

(fd 3 is also open, but the check only starts at 4 for some reason.)

For xl, this is the poller created by libxl_ctx_alloc, the poller
created by do_domain_create -> libxl__ao_create, and the self pipe for
libxl__sigchld_needed.  Set CLOEXEC on the FDs so they are not leaked
into children.

Signed-off-by: Jason Andryuk <jandryuk@gmail.com>
---
Maybe the setting wants to move into libxl__pipe_nonblock()?  Poller &
sigchld are the only callers of that function.
---
 tools/libs/light/libxl_event.c | 3 +++
 tools/libs/light/libxl_fork.c  | 2 ++
 2 files changed, 5 insertions(+)

Comments

Anthony PERARD May 31, 2022, 5:21 p.m. UTC | #1
On Tue, May 24, 2022 at 12:31:52PM -0400, Jason Andryuk wrote:
> libxl is leaking self pipes to child processes.  These can be seen when
> running with env var _LIBXL_DEBUG_EXEC_FDS=1:
> 
> libxl: debug: libxl_aoutils.c:593:libxl__async_exec_start: forking to execute: /etc/xen/scripts/vif-bridge online
> [Detaching after fork from child process 5099]
> libxl: execing /etc/xen/scripts/vif-bridge: fd 4 is open to pipe:[46805] with flags 0
> libxl: execing /etc/xen/scripts/vif-bridge: fd 13 is open to pipe:[46807] with flags 0
> libxl: execing /etc/xen/scripts/vif-bridge: fd 14 is open to pipe:[46807] with flags 0
> libxl: execing /etc/xen/scripts/vif-bridge: fd 19 is open to pipe:[48570] with flags 0
> libxl: execing /etc/xen/scripts/vif-bridge: fd 20 is open to pipe:[48570] with flags 0
> 
> (fd 3 is also open, but the check only starts at 4 for some reason.)
> 
> For xl, this is the poller created by libxl_ctx_alloc, the poller
> created by do_domain_create -> libxl__ao_create, and the self pipe for
> libxl__sigchld_needed.  Set CLOEXEC on the FDs so they are not leaked
> into children.
> 
> Signed-off-by: Jason Andryuk <jandryuk@gmail.com>
> ---
> Maybe the setting wants to move into libxl__pipe_nonblock()?  Poller &
> sigchld are the only callers of that function.

No because we could want a pipe which survive fork/exec. The function
would need to be renamed. I think it's fine to set cloexec on the spot.

> ---
> diff --git a/tools/libs/light/libxl_event.c b/tools/libs/light/libxl_event.c
> index c8bcd13960..8d24613921 100644
> --- a/tools/libs/light/libxl_event.c
> +++ b/tools/libs/light/libxl_event.c
> @@ -1800,6 +1800,9 @@ int libxl__poller_init(libxl__gc *gc, libxl__poller *p)
>      rc = libxl__pipe_nonblock(CTX, p->wakeup_pipe);
>      if (rc) goto out;
>  
> +    libxl_fd_set_cloexec(CTX, p->wakeup_pipe[0], 1);
> +    libxl_fd_set_cloexec(CTX, p->wakeup_pipe[1], 1);

I think that's ok. I tried to find out if pollers needs to survive a
fork/exec, but that doesn't seems to be the case. Pollers are only used
by libxl's event machinery, and in a single CTX I think.

> diff --git a/tools/libs/light/libxl_fork.c b/tools/libs/light/libxl_fork.c
> index 676a14bb28..b13659d231 100644
> --- a/tools/libs/light/libxl_fork.c
> +++ b/tools/libs/light/libxl_fork.c
> @@ -387,6 +387,8 @@ int libxl__sigchld_needed(libxl__gc *gc) /* non-reentrant, idempotent */
>      if (CTX->sigchld_selfpipe[0] < 0) {
>          rc = libxl__pipe_nonblock(CTX, CTX->sigchld_selfpipe);
>          if (rc) goto out;
> +        libxl_fd_set_cloexec(CTX, CTX->sigchld_selfpipe[0], 1);
> +        libxl_fd_set_cloexec(CTX, CTX->sigchld_selfpipe[1], 1);

These ones should be also ok, as the pipe is only used for the SIGCHLD
handler so not shared outside of libxl.


So the patch looks good, and hopefully we don't break libvirt.

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

Thanks,
diff mbox series

Patch

diff --git a/tools/libs/light/libxl_event.c b/tools/libs/light/libxl_event.c
index c8bcd13960..8d24613921 100644
--- a/tools/libs/light/libxl_event.c
+++ b/tools/libs/light/libxl_event.c
@@ -1800,6 +1800,9 @@  int libxl__poller_init(libxl__gc *gc, libxl__poller *p)
     rc = libxl__pipe_nonblock(CTX, p->wakeup_pipe);
     if (rc) goto out;
 
+    libxl_fd_set_cloexec(CTX, p->wakeup_pipe[0], 1);
+    libxl_fd_set_cloexec(CTX, p->wakeup_pipe[1], 1);
+
     return 0;
 
  out:
diff --git a/tools/libs/light/libxl_fork.c b/tools/libs/light/libxl_fork.c
index 676a14bb28..b13659d231 100644
--- a/tools/libs/light/libxl_fork.c
+++ b/tools/libs/light/libxl_fork.c
@@ -387,6 +387,8 @@  int libxl__sigchld_needed(libxl__gc *gc) /* non-reentrant, idempotent */
     if (CTX->sigchld_selfpipe[0] < 0) {
         rc = libxl__pipe_nonblock(CTX, CTX->sigchld_selfpipe);
         if (rc) goto out;
+        libxl_fd_set_cloexec(CTX, CTX->sigchld_selfpipe[0], 1);
+        libxl_fd_set_cloexec(CTX, CTX->sigchld_selfpipe[1], 1);
     }
     if (!libxl__ev_fd_isregistered(&CTX->sigchld_selfpipe_efd)) {
         rc = libxl__ev_fd_register(gc, &CTX->sigchld_selfpipe_efd,