diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index eaec7cd80c..4e66296983 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1653,7 +1653,10 @@ full_system_sync (OstreeSysroot *self, SyncStats *out_stats, GCancellable *cance GLNX_AUTO_PREFIX_ERROR ("Full sync", error); ot_journal_print (LOG_INFO, "Starting syncfs() for system root"); guint64 start_msec = g_get_monotonic_time () / 1000; - if (syncfs (self->sysroot_fd) != 0) + glnx_autofd int sysroot_dir_fd = -1; + if (!glnx_opendirat (self->sysroot_fd, ".", TRUE, &sysroot_dir_fd, error)) + return FALSE; + if (syncfs (sysroot_dir_fd) != 0) return glnx_throw_errno_prefix (error, "syncfs(sysroot)"); guint64 end_msec = g_get_monotonic_time () / 1000; ot_journal_print (LOG_INFO, "Completed syncfs() for system root in %" G_GUINT64_FORMAT " ms", @@ -1667,7 +1670,10 @@ full_system_sync (OstreeSysroot *self, SyncStats *out_stats, GCancellable *cance g_assert_cmpint (self->boot_fd, !=, -1); ot_journal_print (LOG_INFO, "Starting freeze/thaw cycle for system root"); start_msec = g_get_monotonic_time () / 1000; - if (!fsfreeze_thaw_cycle (self, self->boot_fd, cancellable, error)) + glnx_autofd int boot_dir_fd = -1; + if (!glnx_opendirat (self->boot_fd, ".", TRUE, &boot_dir_fd, error)) + return FALSE; + if (!fsfreeze_thaw_cycle (self, boot_dir_fd, cancellable, error)) return FALSE; end_msec = g_get_monotonic_time () / 1000; ot_journal_print (LOG_INFO, @@ -3340,10 +3346,7 @@ _ostree_sysroot_run_in_deployment (OstreeSysroot *sysroot, int deployment_dfd, gboolean success = FALSE; gboolean in_root; - if (!_ostree_in_root_mount_namespace (&in_root, error)) - return FALSE; - - if (!_ostree_sysroot_enter_mount_namespace (sysroot, error)) + if (!_ostree_sysroot_enter_mount_namespace (sysroot, &in_root, error)) return FALSE; g_autoptr (GPtrArray) args = g_ptr_array_new (); @@ -3383,17 +3386,8 @@ _ostree_sysroot_run_in_deployment (OstreeSysroot *sysroot, int deployment_dfd, success = g_spawn_sync (NULL, (char **)args->pdata, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, (gpointer)(uintptr_t)deployment_dfd, stdout, NULL, exit_status, error); - /* Switch back */ - if (in_root) - { - glnx_autofd int root_ns_fd = -1; - - if (!glnx_openat_rdonly (AT_FDCWD, "/proc/1/ns/mnt", TRUE, &root_ns_fd, error)) - return FALSE; - - if (setns (root_ns_fd, CLONE_NEWNS) < 0) - return glnx_throw_errno_prefix (error, "setns"); - } + if (in_root && !_ostree_enter_root_mount_namespace (error)) + return FALSE; fail: for (int *it = bind_fds; it && *it >= 0; it++) diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index da9f61e267..83d36692eb 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -113,9 +113,13 @@ struct OstreeSysroot // Relative to /boot, consumed by ostree-boot-complete.service #define _OSTREE_FINALIZE_STAGED_FAILURE_PATH "ostree/finalize-failure.stamp" +gboolean _ostree_sysroot_ensure_sysroot_fd (OstreeSysroot *self, GError **error); + gboolean _ostree_in_root_mount_namespace (gboolean *out_val, GError **error); -gboolean _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error); +gboolean _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, gboolean *out_in_root, GError **error); + +gboolean _ostree_enter_root_mount_namespace (GError **error); gboolean _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error); diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 2339591022..01687708e2 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -277,8 +277,8 @@ ostree_sysroot_set_mount_namespace_in_use (OstreeSysroot *self) g_assert (_ostree_in_root_mount_namespace (&in_root, &local_error) && !in_root); } -static gboolean -ensure_sysroot_fd (OstreeSysroot *self, GError **error); +gboolean +_ostree_sysroot_ensure_sysroot_fd (OstreeSysroot *self, GError **error); gboolean _ostree_sysroot_ensure_boot_fd (OstreeSysroot *self, GError **error); @@ -287,14 +287,17 @@ static gboolean _ostree_sysroot_invisible (const OstreeSysroot *self, gboolean *out_val, GError **error); gboolean -_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error) +_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, gboolean *out_in_root, GError **error) { + gboolean in_root_stub; + if (!out_in_root) + out_in_root = &in_root_stub; + /* We also assume operating on non-booted roots won't have a readonly sysroot */ if (!self->root_is_ostree_booted) return TRUE; - gboolean in_root; - if (!_ostree_in_root_mount_namespace (&in_root, error)) + if (!_ostree_in_root_mount_namespace (out_in_root, error)) return FALSE; /* Backup tree fd of sysroot_fd and boot_fd */ @@ -326,7 +329,7 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error) } // If the mount namespaces are the same, we need to unshare(). - if (in_root) + if (*out_in_root) { if (unshare (CLONE_NEWNS) < 0) return glnx_throw_errno_prefix (error, "Failed to invoke unshare(CLONE_NEWNS)"); @@ -338,7 +341,7 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error) /* Mount sysroot and boot back */ ostree_sysroot_unload (self); - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; gboolean invisible; @@ -376,6 +379,20 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error) return TRUE; } +gboolean +_ostree_enter_root_mount_namespace (GError **error) +{ + glnx_autofd int root_ns_fd = -1; + + if (!glnx_openat_rdonly (AT_FDCWD, "/proc/1/ns/mnt", TRUE, &root_ns_fd, error)) + return FALSE; + + if (setns (root_ns_fd, CLONE_NEWNS) < 0) + return glnx_throw_errno_prefix (error, "setns"); + + return TRUE; +} + /** * ostree_sysroot_initialize_with_mount_namespace: * @@ -406,7 +423,7 @@ ostree_sysroot_initialize_with_mount_namespace (OstreeSysroot *self, GCancellabl if (!ostree_sysroot_initialize (self, error)) return FALSE; - return _ostree_sysroot_enter_mount_namespace (self, error); + return _ostree_sysroot_enter_mount_namespace (self, NULL, error); } /** @@ -422,8 +439,8 @@ ostree_sysroot_get_path (OstreeSysroot *self) } /* Open a directory file descriptor for the sysroot if we haven't yet */ -static gboolean -ensure_sysroot_fd (OstreeSysroot *self, GError **error) +gboolean +_ostree_sysroot_ensure_sysroot_fd (OstreeSysroot *self, GError **error) { if (self->sysroot_fd == -1) { @@ -566,10 +583,7 @@ _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error) return FALSE; gboolean in_root; - if (!_ostree_in_root_mount_namespace (&in_root, error)) - return FALSE; - - if (!_ostree_sysroot_enter_mount_namespace (self, error)) + if (!_ostree_sysroot_enter_mount_namespace (self, &in_root, error)) return FALSE; ostree_sysroot_unload (self); @@ -584,7 +598,7 @@ _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error) if (!remount_writable (boot_path, &did_remount_boot, error)) return FALSE; - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; glnx_autofd int old_sysroot_fd = g_steal_fd (&self->sysroot_fd); if ((self->sysroot_fd = (int)syscall (SYS_open_tree, old_sysroot_fd, "sysroot", 1 /* OPEN_TREE_CLONE */ | O_CLOEXEC)) < 0) @@ -592,17 +606,8 @@ _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error) if ((self->boot_fd = (int)syscall (SYS_open_tree, old_sysroot_fd, "boot", 1 /* OPEN_TREE_CLONE */ | O_CLOEXEC)) < 0) return glnx_throw_errno_prefix (error, "open_tree"); - /* Switch back */ - if (in_root) - { - glnx_autofd int root_ns_fd = -1; - - if (!glnx_openat_rdonly (AT_FDCWD, "/proc/1/ns/mnt", TRUE, &root_ns_fd, error)) - return FALSE; - - if (setns (root_ns_fd, CLONE_NEWNS) < 0) - return glnx_throw_errno_prefix (error, "setns"); - } + if (in_root && !_ostree_enter_root_mount_namespace (error)) + return FALSE; return TRUE; } @@ -682,7 +687,7 @@ ostree_sysroot_unload (OstreeSysroot *self) gboolean ostree_sysroot_ensure_initialized (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, "ostree/repo", 0755, cancellable, error)) @@ -736,7 +741,7 @@ _ostree_sysroot_read_current_subbootversion (OstreeSysroot *self, int bootversio { GLNX_AUTO_PREFIX_ERROR ("Reading current subbootversion", error); - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; g_autofree char *ostree_bootdir_name = g_strdup_printf ("ostree/boot.%d", bootversion); @@ -802,7 +807,7 @@ _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion, GPtrArray **out_loader_configs, GCancellable *cancellable, GError **error) { - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; g_autoptr (GPtrArray) ret_loader_configs @@ -963,7 +968,7 @@ static gboolean parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment **out_deployment, GCancellable *cancellable, GError **error) { - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; int entry_boot_version; @@ -1177,7 +1182,7 @@ ensure_repo (OstreeSysroot *self, GError **error) if (self->repo != NULL) return TRUE; - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; self->repo = ostree_repo_open_at (self->sysroot_fd, "ostree/repo", NULL, error); if (!self->repo) @@ -1215,7 +1220,7 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error) { GLNX_AUTO_PREFIX_ERROR ("Initializing sysroot", error); - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; if (self->loadstate < OSTREE_SYSROOT_LOAD_STATE_INIT) @@ -1877,7 +1882,7 @@ ostree_sysroot_origin_new_from_refspec (OstreeSysroot *self, const char *refspec gboolean ostree_sysroot_lock (OstreeSysroot *self, GError **error) { - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; if (!_ostree_sysroot_ensure_writable (self, error)) @@ -1904,7 +1909,7 @@ ostree_sysroot_lock (OstreeSysroot *self, GError **error) gboolean ostree_sysroot_try_lock (OstreeSysroot *self, gboolean *out_acquired, GError **error) { - if (!ensure_sysroot_fd (self, error)) + if (!_ostree_sysroot_ensure_sysroot_fd (self, error)) return FALSE; if (!_ostree_sysroot_ensure_writable (self, error))