core: Make unprivileged case ignore ownership, add "_compose" context

I was in the process of trying to support `%post` scripts, and I
wanted to use `rpm-ostree container` for convenient and safe testing.
However the recent package layering changes broke it to error out
on perms like `filesystem`'s `root:mail` on `/var/mail`.

I decided to introduce a new `rpmostree_context_new_compose` which had
the current behavior, switch `compose tree` to use it, and then change
`_new_unprivileged` to *really* be unprivileged.  Specifically we
ignore file ownership (and fix dir owners) because we assume we'll be
operating with `bare-user` repos.

Closes: #327
Approved by: jlebon
This commit is contained in:
Colin Walters 2016-06-16 08:52:29 -04:00 committed by Atomic Bot
parent 5936b53812
commit 3c77c36999
5 changed files with 66 additions and 14 deletions

View File

@ -689,7 +689,7 @@ rpmostree_compose_builtin_tree (int argc,
goto out;
}
corectx = rpmostree_context_new_unprivileged (self->cachedir_dfd, cancellable, error);
corectx = rpmostree_context_new_compose (self->cachedir_dfd, cancellable, error);
if (!corectx)
goto out;

View File

@ -275,6 +275,7 @@ struct _RpmOstreeContext {
RpmOstreeTreespec *spec;
HifContext *hifctx;
OstreeRepo *ostreerepo;
gboolean unprivileged;
char *dummy_instroot_path;
OstreeSePolicy *sepolicy;
};
@ -356,8 +357,9 @@ rpmostree_context_new_system (GCancellable *cancellable,
return self;
}
RpmOstreeContext *
rpmostree_context_new_unprivileged (int userroot_dfd,
static RpmOstreeContext *
rpmostree_context_new_internal (int userroot_dfd,
gboolean unprivileged,
GCancellable *cancellable,
GError **error)
{
@ -367,6 +369,8 @@ rpmostree_context_new_unprivileged (int userroot_dfd,
if (!ret)
goto out;
ret->unprivileged = unprivileged;
{ g_autofree char *reposdir = glnx_fdrel_abspath (userroot_dfd, "rpmmd.repos.d");
hif_context_set_repo_dir (ret->hifctx, reposdir);
}
@ -408,6 +412,22 @@ rpmostree_context_new_unprivileged (int userroot_dfd,
return NULL;
}
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);
}
/* XXX: or put this in new_system() instead? */
void
rpmostree_context_set_repo (RpmOstreeContext *self,
@ -1290,7 +1310,7 @@ rpmostree_context_download (RpmOstreeContext *ctx,
}
static gboolean
import_one_package (OstreeRepo *ostreerepo,
import_one_package (RpmOstreeContext *self,
HifContext *hifctx,
HifPackage *pkg,
OstreeSePolicy *sepolicy,
@ -1298,6 +1318,7 @@ import_one_package (OstreeRepo *ostreerepo,
GError **error)
{
gboolean ret = FALSE;
OstreeRepo *ostreerepo = self->ostreerepo;
g_autofree char *ostree_commit = NULL;
glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
g_autofree char *pkg_path;
@ -1314,6 +1335,8 @@ import_one_package (OstreeRepo *ostreerepo,
}
flags = RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION;
if (self->unprivileged)
flags |= RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED;
/* TODO - tweak the unpacker flags for containers */
unpacker = rpmostree_unpacker_new_at (AT_FDCWD, pkg_path, flags, error);
@ -1369,7 +1392,7 @@ rpmostree_context_import (RpmOstreeContext *self,
for (guint i = 0; i < install->packages_to_import->len; i++)
{
HifPackage *pkg = install->packages_to_import->pdata[i];
if (!import_one_package (self->ostreerepo, hifctx, pkg,
if (!import_one_package (self, hifctx, pkg,
self->sepolicy, cancellable, error))
goto out;
hif_state_assert_done (hifstate);

View File

@ -38,6 +38,10 @@ G_DECLARE_FINAL_TYPE (RpmOstreeInstall, rpmostree_install, RPMOSTREE, INSTALL, G
RpmOstreeContext *rpmostree_context_new_system (GCancellable *cancellable,
GError **error);
RpmOstreeContext *rpmostree_context_new_compose (int basedir_dfd,
GCancellable *cancellable,
GError **error);
RpmOstreeContext *rpmostree_context_new_unprivileged (int basedir_dfd,
GCancellable *cancellable,
GError **error);

View File

@ -503,7 +503,7 @@ typedef struct
} cb_data;
static OstreeRepoCommitFilterResult
filter_cb (OstreeRepo *repo,
compose_filter_cb (OstreeRepo *repo,
const char *path,
GFileInfo *file_info,
gpointer user_data)
@ -511,7 +511,7 @@ filter_cb (OstreeRepo *repo,
RpmOstreeUnpacker *self = ((cb_data*)user_data)->self;
GError **error = ((cb_data*)user_data)->error;
/* For now we fail if an RPM requires a file to be owned by non-root. The
/* In the system case, fail if an RPM requires a file to be owned by non-root. The
* problem is that RPM provides strings, but ostree records uids/gids. Any
* mapping we choose would be specific to a certain userdb and thus not
* portable. To properly support this will probably require switching over to
@ -548,6 +548,23 @@ filter_cb (OstreeRepo *repo,
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
}
static OstreeRepoCommitFilterResult
unprivileged_filter_cb (OstreeRepo *repo,
const char *path,
GFileInfo *file_info,
gpointer user_data)
{
guint32 mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
/* Fedora changed the directories to not be writable by root for bad
* reasons, which isn't useful here since we expect people to slap a
* ro bind mount on top, so let's just mark as writable by user.
*/
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
mode |= S_IWUSR;
g_file_info_set_attribute_uint32 (file_info, "unix::mode", mode);
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
}
static GVariant*
xattr_cb (OstreeRepo *repo,
const char *path,
@ -596,8 +613,14 @@ import_rpm_to_repo (RpmOstreeUnpacker *self,
GError *cb_error = NULL;
cb_data fdata = { self, &cb_error };
OstreeRepoCommitFilter filter;
modifier = ostree_repo_commit_modifier_new (0, filter_cb, &fdata, NULL);
if ((self->flags & RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED) > 0)
filter = unprivileged_filter_cb;
else
filter = compose_filter_cb;
modifier = ostree_repo_commit_modifier_new (0, filter, &fdata, NULL);
ostree_repo_commit_modifier_set_xattr_callback (modifier, xattr_cb,
NULL, self);
ostree_repo_commit_modifier_set_sepolicy (modifier, sepolicy);

View File

@ -36,9 +36,11 @@ GType rpmostree_unpacker_get_type (void);
/**
* RpmOstreeUnpackerFlags:
* @RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION: Move files to follow ostree convention
* @RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED: Ignore file ownership and setuid modes
*/
typedef enum {
RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION = (1 << 0)
RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION = (1 << 0),
RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED = (1 << 1)
} RpmOstreeUnpackerFlags;
RpmOstreeUnpacker*