Skip to content

Commit

Permalink
WIP: main: Also automatically remount rw /sysroot for ostree pull etc.
Browse files Browse the repository at this point in the history
See coreos/fedora-coreos-tracker#343
When we added the read-only sysroot support it broke using "raw"
`ostree pull` and `ostree refs --create` and all of the core repo
CLIs that just operate on a repo and not a sysroot.

Fixing this is a bit ugly as it "layer crosses" things even more.
Extract a helper function that works in both cases.
  • Loading branch information
cgwalters committed Mar 12, 2020
1 parent 26a2be0 commit 229ddad
Showing 1 changed file with 54 additions and 21 deletions.
75 changes: 54 additions & 21 deletions src/ostree/ot-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
#include <sys/mount.h>
#include <linux/fs.h>

#include "ot-main.h"
#include "ostree.h"
Expand Down Expand Up @@ -292,6 +294,46 @@ ostree_parse_sysroot_or_repo_option (GOptionContext *context,
return TRUE;
}


static gboolean
ostree_maybe_setup_mount_namespace (gboolean *out_ns,
GError **error)
{
*out_ns = FALSE;

/* If we're not root, then we almost certainly can't be remounting anything */
if (getuid () != 0)
return TRUE;

/* If the system isn't booted via libostree, also nothing to do */
if (!glnx_fstatat_allow_noent (AT_FDCWD, "/run/ostree-booted", NULL, 0, error))
return FALSE;
if (errno == ENOENT)
return TRUE;

glnx_autofd int sysroot_subdir_fd = glnx_opendirat_with_errno (AT_FDCWD, "/sysroot", TRUE);
if (sysroot_subdir_fd < 0)
{
if (errno != ENOENT)
return glnx_throw_errno_prefix (error, "opendirat");
/* No /sysroot - nothing to do */
return TRUE;
}

struct statvfs stvfs;
if (fstatvfs (sysroot_subdir_fd, &stvfs) < 0)
return glnx_throw_errno_prefix (error, "fstatvfs");
if (stvfs.f_flag & ST_RDONLY)
{
if (unshare (CLONE_NEWNS) < 0)
return glnx_throw_errno_prefix (error, "preparing writable sysroot: unshare (CLONE_NEWNS)");

*out_ns = TRUE;
}

return TRUE;
}

gboolean
ostree_option_context_parse (GOptionContext *context,
const GOptionEntry *main_entries,
Expand Down Expand Up @@ -387,6 +429,14 @@ ostree_option_context_parse (GOptionContext *context,
cancellable, error);
if (!repo)
return FALSE;
gboolean setup_ns = FALSE;
if (!ostree_maybe_setup_mount_namespace (&setup_ns, error))
return FALSE;
if (setup_ns)
{
if (mount ("/sysroot", "/sysroot", NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
return glnx_throw_errno_prefix (error, "Remounting /sysroot rw");
}
}

if (out_repo)
Expand Down Expand Up @@ -452,27 +502,10 @@ ostree_admin_option_context_parse (GOptionContext *context,
*/
if (ostree_sysroot_is_booted (sysroot))
{
int sysroot_fd = ostree_sysroot_get_fd (sysroot);
g_assert_cmpint (sysroot_fd, !=, -1);

glnx_autofd int sysroot_subdir_fd = glnx_opendirat_with_errno (sysroot_fd, "sysroot", TRUE);
if (sysroot_subdir_fd < 0)
{
if (errno != ENOENT)
return glnx_throw_errno_prefix (error, "opendirat");
}
else if (getuid () == 0)
{
struct statvfs stvfs;
if (fstatvfs (sysroot_subdir_fd, &stvfs) < 0)
return glnx_throw_errno_prefix (error, "fstatvfs");
if (stvfs.f_flag & ST_RDONLY)
{
if (unshare (CLONE_NEWNS) < 0)
return glnx_throw_errno_prefix (error, "preparing writable sysroot: unshare (CLONE_NEWNS)");
ostree_sysroot_set_mount_namespace_in_use (sysroot);
}
}
gboolean setup_ns = FALSE;
if (!ostree_maybe_setup_mount_namespace (&setup_ns, error))
return FALSE;
ostree_sysroot_set_mount_namespace_in_use (sysroot);
}

/* Released when sysroot is finalized, or on process exit */
Expand Down

0 comments on commit 229ddad

Please sign in to comment.