Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

postprocess: Automatically propagate user.ostreemeta xattrs in commit #3657

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/libpriv/rpmostree-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ G_BEGIN_DECLS
#define RPMOSTREE_DIR_CACHE_SOLV "solv"
#define RPMOSTREE_DIR_LOCK "lock"

// Extended attribute used at build time.
#define RPMOSTREE_USER_IMA "user.ima"
#define RPMOSTREE_SYSTEM_IMA "security.ima"

/* See http://lists.rpm.org/pipermail/rpm-maint/2017-October/006681.html */
/* This is also defined on the Rust side. */
#define RPMOSTREE_RPMDB_LOCATION "usr/share/rpm"
Expand Down
50 changes: 45 additions & 5 deletions src/libpriv/rpmostree-postprocess.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,30 @@ struct CommitThreadData
GError **error;
};

// In unified core mode, we'll see user-mode checkout files.
// What we want for now is to access the embedded xattr values
// which (along with other canonical file metadata) have been serialized
// into the `user.ostreemeta` extended attribute. What we should
// actually do is add nice support for this in core ostree, and also
// automatically pick up file owner for example. This would be a key
// thing to unblock fully unprivileged builds.
//
// But for now, just slurp up the xattrs so we get IMA in particular.
static void
extend_ostree_xattrs (GVariantBuilder *builder, GVariant *vbytes)
{
g_autoptr (GBytes) bytes = g_variant_get_data_as_bytes (vbytes);
g_autoptr (GVariant) filemeta = g_variant_ref_sink (
g_variant_new_from_bytes (OSTREE_FILEMETA_GVARIANT_FORMAT, bytes, false));
g_autoptr (GVariant) xattrs = g_variant_get_child_value (filemeta, 3);
g_autoptr (GVariantIter) viter = g_variant_iter_new (xattrs);
GVariant *key, *value;
while (g_variant_iter_loop (viter, "(@ay@ay)", &key, &value))
{
g_variant_builder_add (builder, "(@ay@ay)", key, value);
}
}

/* Filters out all xattrs that aren't accepted. */
static GVariant *
filter_xattrs_cb (OstreeRepo *repo, const char *relpath, GFileInfo *file_info, gpointer user_data)
Expand All @@ -651,7 +675,7 @@ filter_xattrs_cb (OstreeRepo *repo, const char *relpath, GFileInfo *file_info, g
static const char *accepted_xattrs[] = {
"security.capability", /* https://lwn.net/Articles/211883/ */
"user.pax.flags", /* https://github.com/projectatomic/rpm-ostree/issues/412 */
"user.ima" /* will be replaced with security.ima */
RPMOSTREE_USER_IMA, /* will be replaced with security.ima */
};
g_autoptr (GVariant) existing_xattrs = NULL;
g_autoptr (GVariantIter) viter = NULL;
Expand All @@ -660,6 +684,7 @@ filter_xattrs_cb (OstreeRepo *repo, const char *relpath, GFileInfo *file_info, g
GVariant *key, *value;
GVariantBuilder builder;

// From here, ensure the path is relative
if (relpath[0] == '/')
relpath++;

Expand All @@ -686,15 +711,30 @@ filter_xattrs_cb (OstreeRepo *repo, const char *relpath, GFileInfo *file_info, g

while (g_variant_iter_loop (viter, "(@ay@ay)", &key, &value))
{
const char *attrkey = g_variant_get_bytestring (key);

// If it's the special bare-user xattr, then slurp out the embedded
// xattrs.
if (g_str_equal (attrkey, "user.ostreemeta"))
{
extend_ostree_xattrs (&builder, value);
continue;
}

// Otherwise, process our allowlist of xattrs.
for (guint i = 0; i < G_N_ELEMENTS (accepted_xattrs); i++)
{
const char *validkey = accepted_xattrs[i];
const char *attrkey = g_variant_get_bytestring (key);
if (g_str_equal (validkey, attrkey))
{
if (g_str_equal (validkey, "user.ima"))
g_variant_builder_add (&builder, "(@ay@ay)",
g_variant_new_bytestring ("security.ima"), value);
// Translate user.ima to its final security.ima value. This allows handling
// IMA outside of rpm-ostree, without needing IMA to be enabled on the
// "host" system.
if (g_str_equal (validkey, RPMOSTREE_USER_IMA))
{
g_variant_builder_add (&builder, "(@ay@ay)",
g_variant_new_bytestring (RPMOSTREE_SYSTEM_IMA), value);
}
else
g_variant_builder_add (&builder, "(@ay@ay)", key, value);
}
Expand Down