From cfedbcd88877c7d4c71ea14e77b5e2f72d06fb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Sun, 29 Oct 2017 13:19:10 +0100 Subject: bubblewrap: Do not leak FDs dedicated to setup_newroot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The options --file, --bind-data and --ro-bind-data take a file descriptor as first argument. This FD is then used to set up the new root file system. These FDs are then closed after this step. However, when the privileged mode is used, this step is run in a child process, hence leaking the FDs in the parent process. To avoid future omissions, this patch walk through all the file descriptors tied to an option and try to close them. To avoid a double close, it marks FDs closed by setup_newroot as such. Signed-off-by: Mickaël Salaün Closes: #243 Approved by: cgwalters --- bubblewrap.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bubblewrap.c b/bubblewrap.c index 230a67d..8f7d358 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -1147,6 +1147,7 @@ setup_newroot (bool unshare_pid, die_with_error ("Can't write data to file %s", op->dest); close (op->fd); + op->fd = -1; } break; @@ -1164,6 +1165,7 @@ setup_newroot (bool unshare_pid, die_with_error ("Can't write data to file %s", op->dest); close (op->fd); + op->fd = -1; assert (dest != NULL); @@ -1203,6 +1205,22 @@ setup_newroot (bool unshare_pid, PRIV_SEP_OP_DONE, 0, NULL, NULL); } +/* Do not leak file descriptors already used by setup_newroot () */ +static void +close_ops_fd (void) +{ + SetupOp *op; + + for (op = ops; op != NULL; op = op->next) + { + if (op->fd != -1) + { + (void) close (op->fd); + op->fd = -1; + } + } +} + /* We need to resolve relative symlinks in the sandbox before we chroot so that absolute symlinks are handled correctly. We also need to do this after we've switched to the real uid so that @@ -2324,6 +2342,8 @@ main (int argc, setup_newroot (opt_unshare_pid, -1); } + close_ops_fd (); + /* The old root better be rprivate or we will send unmount events to the parent namespace */ if (mount ("oldroot", "oldroot", NULL, MS_REC | MS_PRIVATE, NULL) != 0) die_with_error ("Failed to make old root rprivate"); -- cgit v1.2.1