repo: Add an API to init `OstreeSePolicy` from commit directly
authorColin Walters <walters@verbum.org>
Tue, 28 Sep 2021 21:40:28 +0000 (17:40 -0400)
committerColin Walters <walters@verbum.org>
Thu, 30 Sep 2021 19:54:48 +0000 (15:54 -0400)
This is part of `OstreeCommitModifier`, but I'm not using
that in some of the ostree-ext Rust code.

It just makes more sense as a direct policy API, where it should
have been in the first place.  There's already support for
setting a policy object on a commit modifier, so that's all the
old API needs to do now.

Makefile-libostree.am
apidoc/ostree-sections.txt
src/libostree/libostree-devel.sym
src/libostree/ostree-repo-commit.c
src/libostree/ostree-sepolicy.c
src/libostree/ostree-sepolicy.h

index dd396974064ae6c8107864bad34552bcc5b6e7e6..d40de48d13fe8c7cd9c5d4458ae0e60aa3a55e29 100644 (file)
@@ -173,9 +173,9 @@ endif # USE_GPGME
 symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym
 
 # Uncomment this include when adding new development symbols.
-#if BUILDOPT_IS_DEVEL_BUILD
-#symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
-#endif
+if BUILDOPT_IS_DEVEL_BUILD
+symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
+endif
 
 # http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html
 wl_versionscript_arg = -Wl,--version-script=
index f0901f214cae407ea1cbef5b749bc9e4a6807ea0..ae8abe81aea035e10bb119ba772eef82bd0a8ae6 100644 (file)
@@ -522,6 +522,7 @@ ostree_repo_file_get_type
 OstreeSePolicy
 ostree_sepolicy_new
 ostree_sepolicy_new_at
+ostree_sepolicy_new_from_commit
 ostree_sepolicy_get_path
 ostree_sepolicy_get_name
 ostree_sepolicy_get_label
index e3cd14a4afe56c8312e676914df80f6d08d329e0..35d539567801f04a78cfcbfeb805adc4cde74409 100644 (file)
    - uncomment the include in Makefile-libostree.am
 */
 
+LIBOSTREE_2021.5 {
+global:
+  ostree_sepolicy_new_from_commit;
+} LIBOSTREE_2021.4;
+
 /* Stub section for the stable release *after* this development one; don't
  * edit this other than to update the year.  This is just a copy/paste
  * source.  Replace $LASTSTABLE with the last stable version, and $NEWVERSION
index 8dc2355e9e6511a3915e9efe102c736c1cea7600..c87e8de8921d5a9bf45e638743e0e592458a9657 100644 (file)
@@ -4314,7 +4314,6 @@ ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier)
   g_clear_pointer (&modifier->devino_cache, (GDestroyNotify)g_hash_table_unref);
 
   g_clear_object (&modifier->sepolicy);
-  (void) glnx_tmpdir_delete (&modifier->sepolicy_tmpdir, NULL, NULL);
 
   g_free (modifier);
   return;
@@ -4386,38 +4385,10 @@ ostree_repo_commit_modifier_set_sepolicy_from_commit (OstreeRepoCommitModifier
                                                       GCancellable                          *cancellable,
                                                       GError                               **error)
 {
-  GLNX_AUTO_PREFIX_ERROR ("setting sepolicy from commit", error);
-  g_autofree char *commit = NULL;
-  g_autoptr(GFile) root = NULL;
-  if (!ostree_repo_read_commit (repo, rev, &root, &commit, cancellable, error))
-    return FALSE;
-  const char policypath[] = "usr/etc/selinux";
-  g_autoptr(GFile) policyroot = g_file_get_child (root, policypath);
-  if (!g_file_query_exists (policyroot, NULL))
-    return TRUE;  /* No policy, nothing to do */
-
-  GLnxTmpDir tmpdir = {0,};
-  if (!glnx_mkdtemp ("ostree-commit-sepolicy-XXXXXX", 0700, &tmpdir, error))
-    return FALSE;
-  if (!glnx_shutil_mkdir_p_at (tmpdir.fd, "usr/etc", 0755, cancellable, error))
-    return FALSE;
-
-  OstreeRepoCheckoutAtOptions coopts = {0,};
-  coopts.mode = OSTREE_REPO_CHECKOUT_MODE_USER;
-  coopts.subpath = glnx_strjoina ("/", policypath);
-
-  if (!ostree_repo_checkout_at (repo, &coopts, tmpdir.fd, policypath, commit, cancellable, error))
-    return glnx_prefix_error (error, "policy checkout");
-
-  g_autoptr(OstreeSePolicy) policy = ostree_sepolicy_new_at (tmpdir.fd, cancellable, error);
+  g_autoptr(OstreeSePolicy) policy = ostree_sepolicy_new_from_commit (repo, rev, cancellable, error);
   if (!policy)
-    return glnx_prefix_error (error, "reading policy");
-
+    return FALSE;
   ostree_repo_commit_modifier_set_sepolicy (modifier, policy);
-  /* Transfer ownership */
-  modifier->sepolicy_tmpdir = tmpdir;
-  tmpdir.initialized = FALSE;
-
   return TRUE;
 }
 
index e6b9a0e1d63b2abb1c162865cdc46123a7a5d1b6..8aa1df96f7416bb603e3dcf92a07fc468e49bebb 100644 (file)
@@ -29,6 +29,7 @@
 #include "otutil.h"
 
 #include "ostree-sepolicy.h"
+#include "ostree-repo.h"
 #include "ostree-sepolicy-private.h"
 #include "ostree-bootloader-uboot.h"
 #include "ostree-bootloader-syslinux.h"
@@ -47,6 +48,7 @@ struct OstreeSePolicy {
   int rootfs_dfd;
   int rootfs_dfd_owned;
   GFile *path;
+  GLnxTmpDir tmpdir;
 
 #ifdef HAVE_SELINUX
   GFile *selinux_policy_root;
@@ -77,6 +79,8 @@ ostree_sepolicy_finalize (GObject *object)
 {
   OstreeSePolicy *self = OSTREE_SEPOLICY (object);
 
+  (void) glnx_tmpdir_delete (&self->tmpdir, NULL, NULL);
+
   g_clear_object (&self->path);
   if (self->rootfs_dfd_owned != -1)
     (void) close (self->rootfs_dfd_owned);
@@ -266,6 +270,58 @@ get_policy_checksum (char        **out_csum,
 
 #endif
 
+/**
+ * ostree_sepolicy_new_from_commit:
+ * @repo: The repo
+ * @rev: ostree ref or checksum
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Extract the SELinux policy from a commit object via a partial checkout.  This is useful
+ * for labeling derived content as separate commits.
+ *
+ * This function is the backend of `ostree_repo_commit_modifier_set_sepolicy_from_commit()`.
+ *
+ * Returns: (transfer full): A new policy
+ */
+OstreeSePolicy*
+ostree_sepolicy_new_from_commit (OstreeRepo  *repo,
+                                 const char  *rev,
+                                 GCancellable *cancellable,
+                                 GError     **error)
+{
+  GLNX_AUTO_PREFIX_ERROR ("setting sepolicy from commit", error);
+  g_autoptr(GFile) root = NULL;
+  g_autofree char *commit = NULL;
+  if (!ostree_repo_read_commit (repo, rev, &root, &commit, cancellable, error))
+    return NULL;
+  const char policypath[] = "usr/etc/selinux";
+  g_autoptr(GFile) policyroot = g_file_get_child (root, policypath);
+
+  GLnxTmpDir tmpdir = {0,};
+  if (!glnx_mkdtemp ("ostree-commit-sepolicy-XXXXXX", 0700, &tmpdir, error))
+    return FALSE;
+  if (!glnx_shutil_mkdir_p_at (tmpdir.fd, "usr/etc", 0755, cancellable, error))
+    return FALSE;
+
+  if (g_file_query_exists (policyroot, NULL))
+    {
+       OstreeRepoCheckoutAtOptions coopts = {0,};
+       coopts.mode = OSTREE_REPO_CHECKOUT_MODE_USER;
+       coopts.subpath = glnx_strjoina ("/", policypath);
+     
+       if (!ostree_repo_checkout_at (repo, &coopts, tmpdir.fd, policypath, commit, cancellable, error))
+         return glnx_prefix_error_null (error, "policy checkout");
+    }
+
+  OstreeSePolicy *ret = ostree_sepolicy_new_at (tmpdir.fd, cancellable, error);
+  if (!ret)
+    return NULL;
+  /* Transfer ownership of tmpdir */
+  ret->tmpdir = tmpdir;
+  tmpdir.initialized = FALSE;
+  return ret;
+}
 
 /* Workaround for http://marc.info/?l=selinux&m=149323809332417&w=2 */
 #ifdef HAVE_SELINUX
index 7e90527fc64e0afce71a8a80728729d1e98838eb..0e8cf5af0db43917967a8c5d0627652e70666be0 100644 (file)
@@ -44,6 +44,11 @@ OstreeSePolicy* ostree_sepolicy_new_at (int            rootfs_dfd,
                                         GCancellable  *cancellable,
                                         GError       **error);
 
+_OSTREE_PUBLIC
+OstreeSePolicy* ostree_sepolicy_new_from_commit (OstreeRepo  *repo,
+                                                 const char  *rev,
+                                                 GCancellable *cancellable,
+                                                 GError     **error);
 
 _OSTREE_PUBLIC
 GFile * ostree_sepolicy_get_path (OstreeSePolicy  *self);