Change ex-container to use BARE_USER_ONLY, update core creation API

Switch `ex container` to `OSTREE_REPO_MODE_BARE_USER_ONLY`; this is a good
match, for the same reasons as flatpak. We don't want suid binaries, we don't
want to chown anything, no SELinux labeling, etc.  There's no reason to write the
metadata to the `BARE_USER` xattrs.

The "unprivileged" context as used for `ex container` was a flag that was passed
down, but I think it's a lot easier if things just infer this state by looking
at whether the target repo is `bare-user-only`. Now we just have an
`rpmostree_context_new_tree()` API that handles both container and compose.

Closes: #1026
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-09-28 15:47:40 -04:00 committed by Atomic Bot
parent d16d53ecae
commit d4af84d428
6 changed files with 31 additions and 49 deletions

View File

@ -749,7 +749,7 @@ impl_compose_tree (const char *treefile_pathstr,
if (fchdir (self->workdir_dfd) != 0) if (fchdir (self->workdir_dfd) != 0)
return glnx_throw_errno_prefix (error, "fchdir"); return glnx_throw_errno_prefix (error, "fchdir");
self->corectx = rpmostree_context_new_compose (self->cachedir_dfd, cancellable, error); self->corectx = rpmostree_context_new_tree (self->cachedir_dfd, self->repo, cancellable, error);
if (!self->corectx) if (!self->corectx)
return FALSE; return FALSE;

View File

@ -82,6 +82,10 @@ roc_context_init (ROContainerContext *rocctx,
if (!rocctx->repo) if (!rocctx->repo)
return FALSE; return FALSE;
OstreeRepoMode mode = ostree_repo_get_mode (rocctx->repo);
if (mode != OSTREE_REPO_MODE_BARE_USER_ONLY)
return glnx_throw (error, "container repos are now required to be in bare-user-only mode");
if (!glnx_opendirat (rocctx->userroot_dfd, "roots", TRUE, &rocctx->roots_dfd, error)) if (!glnx_opendirat (rocctx->userroot_dfd, "roots", TRUE, &rocctx->roots_dfd, error))
return FALSE; return FALSE;
@ -97,7 +101,8 @@ roc_context_prepare_for_root (ROContainerContext *rocctx,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
rocctx->ctx = rpmostree_context_new_unprivileged (rocctx->userroot_dfd, NULL, error); rocctx->ctx = rpmostree_context_new_tree (rocctx->userroot_dfd, rocctx->repo,
cancellable, error);
if (!rocctx->ctx) if (!rocctx->ctx)
return FALSE; return FALSE;
@ -153,7 +158,7 @@ rpmostree_container_builtin_init (int argc,
} }
rocctx->repo = ostree_repo_create_at (rocctx->userroot_dfd, "repo", rocctx->repo = ostree_repo_create_at (rocctx->userroot_dfd, "repo",
OSTREE_REPO_MODE_BARE_USER, NULL, OSTREE_REPO_MODE_BARE_USER_ONLY, NULL,
cancellable, error); cancellable, error);
if (!rocctx->repo) if (!rocctx->repo)
return FALSE; return FALSE;

View File

@ -347,19 +347,22 @@ rpmostree_context_new_system (GCancellable *cancellable,
return self; return self;
} }
static RpmOstreeContext * /* Create a context that assembles a new filesystem tree, possibly without root
rpmostree_context_new_internal (int userroot_dfd, * privileges. Some behavioral distinctions are made by looking at the undelying
gboolean unprivileged, * OstreeRepoMode. In particular, an OSTREE_REPO_MODE_BARE_USER_ONLY repo
GCancellable *cancellable, * is assumed to be for unprivileged containers/buildroots.
GError **error) */
RpmOstreeContext *
rpmostree_context_new_tree (int userroot_dfd,
OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{ {
g_autoptr(RpmOstreeContext) ret = g_autoptr(RpmOstreeContext) ret =
rpmostree_context_new_system (cancellable, error); rpmostree_context_new_system (cancellable, error);
if (!ret) if (!ret)
return NULL; return NULL;
ret->unprivileged = unprivileged;
{ g_autofree char *reposdir = glnx_fdrel_abspath (userroot_dfd, "rpmmd.repos.d"); { g_autofree char *reposdir = glnx_fdrel_abspath (userroot_dfd, "rpmmd.repos.d");
dnf_context_set_repo_dir (ret->hifctx, reposdir); dnf_context_set_repo_dir (ret->hifctx, reposdir);
} }
@ -377,35 +380,11 @@ rpmostree_context_new_internal (int userroot_dfd,
} }
/* open user root repo if exists (container path) */ /* open user root repo if exists (container path) */
struct stat stbuf; ret->ostreerepo = repo ? g_object_ref (repo) : NULL;
if (!glnx_fstatat_allow_noent (userroot_dfd, "repo", &stbuf, 0, error))
return NULL;
if (errno == 0)
{
ret->ostreerepo = ostree_repo_open_at (userroot_dfd, "repo", cancellable, error);
if (!ret->ostreerepo)
return NULL;
}
return g_steal_pointer (&ret); return g_steal_pointer (&ret);
} }
RpmOstreeContext *
rpmostree_context_new_compose (int basedir_dfd,
GCancellable *cancellable,
GError **error)
{
return rpmostree_context_new_internal (basedir_dfd, FALSE, cancellable, error);
}
RpmOstreeContext *
rpmostree_context_new_unprivileged (int basedir_dfd,
GCancellable *cancellable,
GError **error)
{
return rpmostree_context_new_internal (basedir_dfd, TRUE, cancellable, error);
}
static gboolean static gboolean
rpmostree_context_ensure_tmpdir (RpmOstreeContext *self, rpmostree_context_ensure_tmpdir (RpmOstreeContext *self,
const char *subdir, const char *subdir,
@ -1769,9 +1748,6 @@ import_one_package (RpmOstreeContext *self,
if (!dnf_transaction_gpgcheck_package (dnf_context_get_transaction (hifctx), pkg, error)) if (!dnf_transaction_gpgcheck_package (dnf_context_get_transaction (hifctx), pkg, error))
return FALSE; return FALSE;
if (self->unprivileged)
flags |= RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED;
/* Only set SKIP_EXTRANEOUS for packages we know need it, so that /* Only set SKIP_EXTRANEOUS for packages we know need it, so that
* people doing custom composes don't have files silently discarded. * people doing custom composes don't have files silently discarded.
* (This will also likely need to be configurable). * (This will also likely need to be configurable).

View File

@ -37,13 +37,10 @@ G_DECLARE_FINAL_TYPE (RpmOstreeTreespec, rpmostree_treespec, RPMOSTREE, TREESPEC
RpmOstreeContext *rpmostree_context_new_system (GCancellable *cancellable, RpmOstreeContext *rpmostree_context_new_system (GCancellable *cancellable,
GError **error); GError **error);
RpmOstreeContext *rpmostree_context_new_compose (int basedir_dfd, RpmOstreeContext *rpmostree_context_new_tree (int basedir_dfd,
GCancellable *cancellable, OstreeRepo *repo,
GError **error); GCancellable *cancellable,
GError **error);
RpmOstreeContext *rpmostree_context_new_unprivileged (int basedir_dfd,
GCancellable *cancellable,
GError **error);
DnfContext * rpmostree_context_get_hif (RpmOstreeContext *self); DnfContext * rpmostree_context_get_hif (RpmOstreeContext *self);

View File

@ -713,7 +713,11 @@ import_rpm_to_repo (RpmOstreeUnpacker *self,
cb_data fdata = { self, &cb_error }; cb_data fdata = { self, &cb_error };
OstreeRepoCommitFilter filter; OstreeRepoCommitFilter filter;
if ((self->flags & RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED) > 0) /* This logic replaces our old UNPRIVILEGED flag; we now assume bare-user-only
* is unprivileged, anything else is a compose.
*/
const gboolean unprivileged = ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE_USER_ONLY;
if (unprivileged)
filter = unprivileged_filter_cb; filter = unprivileged_filter_cb;
else else
filter = compose_filter_cb; filter = compose_filter_cb;
@ -721,6 +725,8 @@ import_rpm_to_repo (RpmOstreeUnpacker *self,
/* If changing this, also look at changing rpmostree-postprocess.c */ /* If changing this, also look at changing rpmostree-postprocess.c */
OstreeRepoCommitModifierFlags modifier_flags = OstreeRepoCommitModifierFlags modifier_flags =
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED; OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED;
if (unprivileged)
modifier_flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS;
g_autoptr(OstreeRepoCommitModifier) modifier = g_autoptr(OstreeRepoCommitModifier) modifier =
ostree_repo_commit_modifier_new (modifier_flags, filter, &fdata, NULL); ostree_repo_commit_modifier_new (modifier_flags, filter, &fdata, NULL);
ostree_repo_commit_modifier_set_xattr_callback (modifier, xattr_cb, ostree_repo_commit_modifier_set_xattr_callback (modifier, xattr_cb,

View File

@ -38,12 +38,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (RpmOstreeUnpacker, g_object_unref)
/** /**
* RpmOstreeUnpackerFlags: * RpmOstreeUnpackerFlags:
* @RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED: Ignore file ownership and setuid modes
* @RPMOSTREE_UNPACKER_FLAGS_SKIP_EXTRANEOUS: Skip files/directories outside of supported ostree-compliant paths rather than erroring out * @RPMOSTREE_UNPACKER_FLAGS_SKIP_EXTRANEOUS: Skip files/directories outside of supported ostree-compliant paths rather than erroring out
*/ */
typedef enum { typedef enum {
RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED = (1 << 0), RPMOSTREE_UNPACKER_FLAGS_SKIP_EXTRANEOUS = (1 << 0),
RPMOSTREE_UNPACKER_FLAGS_SKIP_EXTRANEOUS = (1 << 1),
} RpmOstreeUnpackerFlags; } RpmOstreeUnpackerFlags;
RpmOstreeUnpacker* RpmOstreeUnpacker*