From d47b241c726dff8f06319b9643a3574b0d299d09 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Mon, 6 Jan 2020 19:00:44 +0000 Subject: [PATCH] wrap: Tell child process to take out its own lock if necessary Non-OFD locks don't propagate across fork(), and bwrap needs to clone() itself (which behaves like fork() in this respect) to separate itself into a parent outside the container and a child inside the container. This change adds a weak dependency on Linux 3.15. If we run on an older version, everything should still *work*, but there will be a short period of time during which we have already decided to use the runtime, but it is not locked (and in particular not protected from deletion). Fixes: 959fd338 "wrap: Take out a lock on the container's runtime for the duration" Signed-off-by: Simon McVittie <smcv@collabora.com> --- src/bwrap.c | 3 ++- src/wrap.c | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/bwrap.c b/src/bwrap.c index dcd2b11b9..7bdef02f9 100644 --- a/src/bwrap.c +++ b/src/bwrap.c @@ -226,7 +226,8 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, { if (g_str_has_prefix (member, "lib") || g_str_equal (member, "bin") - || g_str_equal (member, "sbin")) + || g_str_equal (member, "sbin") + || g_str_equal (member, ".ref")) { dest = g_build_filename (mount_point, member, NULL); diff --git a/src/wrap.c b/src/wrap.c index e43dce780..7d0c86449 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -4,7 +4,7 @@ * Contains code taken from Flatpak. * * Copyright © 2014-2019 Red Hat, Inc - * Copyright © 2017-2019 Collabora Ltd. + * Copyright © 2017-2020 Collabora Ltd. * * SPDX-License-Identifier: LGPL-2.1-or-later * @@ -2568,15 +2568,46 @@ main (int argc, * can't do that without breaking gameoverlayrender.so's assumptions. */ if (runtime_lock != NULL) { - g_autofree gchar *fd_str = NULL; - int fd = pv_bwrap_lock_steal_fd (runtime_lock); - - fd_str = g_strdup_printf ("%d", fd); - flatpak_bwrap_add_fd (bwrap, fd); flatpak_bwrap_add_args (bwrap, "/run/pressure-vessel/bin/pressure-vessel-with-lock", "--subreaper", - "--fd", fd_str, + NULL); + + if (pv_bwrap_lock_is_ofd (runtime_lock)) + { + int fd = pv_bwrap_lock_steal_fd (runtime_lock); + g_autofree gchar *fd_str = NULL; + + g_debug ("Passing lock fd %d down to with-lock", fd); + flatpak_bwrap_add_fd (bwrap, fd); + fd_str = g_strdup_printf ("%d", fd); + flatpak_bwrap_add_args (bwrap, + "--fd", fd_str, + NULL); + } + else + { + /* + * We were unable to take out an open file descriptor lock, + * so it will be released on fork(). Tell the with-lock process + * to take out its own compatible lock instead. There will be + * a short window during which we have lost our lock but the + * with-lock process has not taken its lock - that's unavoidable + * if we want to use exec() to replace ourselves with the + * container. + * + * pv_bwrap_bind_usr() arranges for /.ref to either be a + * symbolic link to /usr/.ref which is the runtime_lock + * (if opt_runtime is a merged /usr), or the runtime_lock + * itself (otherwise). + */ + g_debug ("Telling process in container to lock /.ref"); + flatpak_bwrap_add_args (bwrap, + "--lock-file", "/.ref", + NULL); + } + + flatpak_bwrap_add_args (bwrap, "--", NULL); } -- GitLab