Skip to content

Commit

Permalink
wip: major unpacker refactoring
Browse files Browse the repository at this point in the history
This is a refactor of a big chunk of the unpacker. It adds proper
selinux labeling support to the unpack_to_dfd path and also solves a
number of subtle issues. The biggest issue solved is proper hardlink
handling. We previously assumed that the data payload was attached to
the first entry in a series of hardlinks. In fact, the payload is in the
*last* entry.  This resulted in any multilinked files all having size 0.

In the unpack_to_dfd path, this works great since we can just re-open
the file at the last hardlink entry to write the actual data. I also
tried implementing this for the unpack_to_ostree path, which was more
complicated since we have to defer imports until we hit the final
hardlink (which requires heuristics to detect).

In the end, I switch the unpack_to_ostree path to simply use a tmprootfs
and then make it call out to unpack_to_dfd. This is less efficient, but
greatly simplifies the whole unpacker code, as well as allowing us to
get rid of the copynpaste stuff.

Eventually, we should probably solve this properly upstream in
ostree_repo_write_archive_to_mtree() and then switch the
unpack_to_ostree codepath to use that.
  • Loading branch information
jlebon committed Apr 12, 2016
1 parent e625f49 commit 8baffc0
Show file tree
Hide file tree
Showing 4 changed files with 502 additions and 578 deletions.
48 changes: 28 additions & 20 deletions src/app/rpmostree-internals-builtin-unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,22 @@ static gboolean opt_suid_fcaps = FALSE;
static gboolean opt_owner = FALSE;
static gboolean opt_to_ostree_repo = FALSE;
static gboolean opt_selinux = FALSE;
static gboolean opt_rwx_dirs = FALSE;
static gboolean opt_ostree_convention = FALSE;

static GOptionEntry option_entries[] = {
{ "suid-fcaps", 0, 0, G_OPTION_ARG_NONE, &opt_suid_fcaps, "Enable setting suid/sgid and capabilities", NULL },
{ "owner", 0, 0, G_OPTION_ARG_NONE, &opt_owner, "Enable chown", NULL },
{ "to-ostree-repo", 0, 0, G_OPTION_ARG_NONE, &opt_to_ostree_repo, "Interpret TARGET as an OSTree repo", NULL },
{ "selinux", 0, 0, G_OPTION_ARG_NONE, &opt_selinux, "Enable setting SELinux labels", NULL },
{ "suid-fcaps", 0, 0, G_OPTION_ARG_NONE, &opt_suid_fcaps,
"Enable setting suid/sgid and capabilities", NULL },
{ "owner", 0, 0, G_OPTION_ARG_NONE, &opt_owner,
"Enable chown", NULL },
{ "to-ostree-repo", 0, 0, G_OPTION_ARG_NONE, &opt_to_ostree_repo,
"Interpret TARGET as an OSTree repo", NULL },
{ "selinux", 0, 0, G_OPTION_ARG_NONE, &opt_selinux,
"Enable setting SELinux labels", NULL },
{ "rwx-dirs", 0, 0, G_OPTION_ARG_NONE, &opt_rwx_dirs,
"Create all dirs with rwx owner bits", NULL },
{ "ostree-convention", 0, 0, G_OPTION_ARG_NONE, &opt_ostree_convention,
"Change file paths following ostree conventions", NULL },
{ NULL }
};

Expand All @@ -67,7 +77,8 @@ rpmostree_internals_builtin_unpack (int argc,
const char *rpmpath;
glnx_fd_close int rootfs_fd = -1;
glnx_unref_object OstreeRepo *ostree_repo = NULL;

glnx_unref_object OstreeSePolicy *sepolicy = NULL;

if (!rpmostree_option_context_parse (context,
option_entries,
&argc, &argv,
Expand All @@ -83,13 +94,6 @@ rpmostree_internals_builtin_unpack (int argc,
goto out;
}

if (opt_selinux && !opt_to_ostree_repo)
{
rpmostree_usage_error (context, "--selinux currently only supported with "
"--to-ostree-repo", error);
goto out;
}

target = argv[1];
rpmpath = argv[2];

Expand All @@ -114,22 +118,25 @@ rpmostree_internals_builtin_unpack (int argc,
flags |= RPMOSTREE_UNPACKER_FLAGS_OWNER;
if (opt_suid_fcaps)
flags |= RPMOSTREE_UNPACKER_FLAGS_SUID_FSCAPS;
if (opt_rwx_dirs)
flags |= RPMOSTREE_UNPACKER_FLAGS_RWX_DIRS;
if (opt_ostree_convention)
flags |= RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION;

unpacker = rpmostree_unpacker_new_at (AT_FDCWD, rpmpath, flags, error);
if (!unpacker)
goto out;

/* just use current policy */
if (opt_selinux)
if (!rpmostree_prepare_rootfs_get_sepolicy (AT_FDCWD, "/", &sepolicy,
cancellable, error))
goto out;

if (opt_to_ostree_repo)
{
const char *branch = rpmostree_unpacker_get_ostree_branch (unpacker);
g_autofree char *checksum = NULL;
glnx_unref_object OstreeSePolicy *sepolicy = NULL;

/* just use current policy */
if (opt_selinux)
if (!rpmostree_prepare_rootfs_get_sepolicy (AT_FDCWD, "/", &sepolicy,
cancellable, error))
goto out;

if (!rpmostree_unpacker_unpack_to_ostree (unpacker, ostree_repo, sepolicy,
&checksum, cancellable, error))
Expand All @@ -139,7 +146,8 @@ rpmostree_internals_builtin_unpack (int argc,
}
else
{
if (!rpmostree_unpacker_unpack_to_dfd (unpacker, rootfs_fd, cancellable, error))
if (!rpmostree_unpacker_unpack_to_dfd (unpacker, rootfs_fd, sepolicy,
cancellable, error))
goto out;
}

Expand Down
11 changes: 7 additions & 4 deletions src/libpriv/rpmostree-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,7 @@ import_one_package (OstreeRepo *ostreerepo,
g_autofree char *ostree_commit = NULL;
glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
g_autofree char *pkg_path;
int flags = 0;

if (pkg_is_local (pkg))
pkg_path = g_strdup (hif_package_get_filename (pkg));
Expand All @@ -1295,11 +1296,13 @@ import_one_package (OstreeRepo *ostreerepo,
g_build_filename (hif_repo_get_location (hif_package_get_repo (pkg)),
"packages", glnx_basename (pkg_location), NULL);
}


flags = RPMOSTREE_UNPACKER_FLAGS_OWNER |
RPMOSTREE_UNPACKER_FLAGS_SUID_FSCAPS |
RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION;

/* TODO - tweak the unpacker flags for containers */
unpacker = rpmostree_unpacker_new_at (AT_FDCWD, pkg_path,
RPMOSTREE_UNPACKER_FLAGS_ALL,
error);
unpacker = rpmostree_unpacker_new_at (AT_FDCWD, pkg_path, flags, error);
if (!unpacker)
goto out;

Expand Down
Loading

0 comments on commit 8baffc0

Please sign in to comment.