[ostree: 6/70] OstreeSePolicy: add ostree_sepolicy_get_csum()
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree: 6/70] OstreeSePolicy: add ostree_sepolicy_get_csum()
- Date: Fri, 15 Apr 2016 21:01:44 +0000 (UTC)
commit b7a04d51f8bc95c6168de155bf625e1ff0ea85ee
Author: Jonathan Lebon <jlebon redhat com>
Date: Wed Mar 23 15:54:49 2016 -0400
OstreeSePolicy: add ostree_sepolicy_get_csum()
This can be used as a fingerprint to determine whether two
OstreeSePolicy objects are equivalent.
Also add documentation for ostree_sepolicy_get_name().
Closes: #219
Approved by: cgwalters
src/libostree/libostree.sym | 1 +
src/libostree/ostree-sepolicy.c | 117 +++++++++++++++++++++++++++++++++++++
src/libostree/ostree-sepolicy.h | 3 +
src/libotutil/ot-checksum-utils.c | 12 ++--
src/libotutil/ot-checksum-utils.h | 9 ++-
5 files changed, 132 insertions(+), 10 deletions(-)
---
diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym
index 47015e1..ca3c6fd 100644
--- a/src/libostree/libostree.sym
+++ b/src/libostree/libostree.sym
@@ -331,4 +331,5 @@ global:
LIBOSTREE_2016.5 {
global:
ostree_repo_import_object_from_with_trust;
+ ostree_sepolicy_get_csum;
} LIBOSTREE_2016.4;
diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c
index b8e3572..3b1a391 100644
--- a/src/libostree/ostree-sepolicy.c
+++ b/src/libostree/ostree-sepolicy.c
@@ -50,6 +50,7 @@ struct OstreeSePolicy {
GFile *selinux_policy_root;
struct selabel_handle *selinux_hnd;
char *selinux_policy_name;
+ char *selinux_policy_csum;
#endif
};
@@ -77,6 +78,7 @@ ostree_sepolicy_finalize (GObject *object)
#ifdef HAVE_SELINUX
g_clear_object (&self->selinux_policy_root);
g_clear_pointer (&self->selinux_policy_name, g_free);
+ g_clear_pointer (&self->selinux_policy_csum, g_free);
if (self->selinux_hnd)
{
selabel_close (self->selinux_hnd);
@@ -155,6 +157,93 @@ ostree_sepolicy_class_init (OstreeSePolicyClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
+#ifdef HAVE_SELINUX
+
+/* Find the latest policy file in our root and return its checksum. */
+static gboolean
+get_policy_checksum (char **out_csum,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+
+ const char *binary_policy_path = selinux_binary_policy_path ();
+ const char *binfile_prefix = glnx_basename (binary_policy_path);
+ g_autofree char *bindir_path = g_path_get_dirname (binary_policy_path);
+
+ glnx_fd_close int bindir_dfd = -1;
+
+ g_autofree char *best_policy = NULL;
+ int best_version = 0;
+
+ g_auto(GLnxDirFdIterator) dfd_iter = { 0,};
+
+ if (!glnx_opendirat (AT_FDCWD, bindir_path, TRUE, &bindir_dfd, error))
+ goto out;
+
+ if (!glnx_dirfd_iterator_init_at (bindir_dfd, ".", FALSE, &dfd_iter, error))
+ goto out;
+
+ while (TRUE)
+ {
+ struct dirent *dent = NULL;
+
+ if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent,
+ cancellable, error))
+ goto out;
+
+ if (dent == NULL)
+ break;
+
+ if (dent->d_type == DT_REG)
+ {
+ /* We could probably save a few hundred nanoseconds if we accept that
+ * the prefix will always be "policy" and hardcode that in a static
+ * compile-once GRegex... But picture how exciting it'd be if it *did*
+ * somehow change; there would be cheers & slow-mo high-fives at the
+ * sight of our code not breaking. Is that hope not worth a fraction
+ * of a millisecond? I believe it is... or maybe I'm just lazy. */
+ g_autofree char *regex = g_strdup_printf ("^\\Q%s\\E\\.[0-9]+$",
+ binfile_prefix);
+
+ /* we could use match groups to extract the version, but mehhh, we
+ * already have the prefix on hand */
+ if (g_regex_match_simple (regex, dent->d_name, 0, 0))
+ {
+ int version = /* do +1 for the period */
+ (int)g_ascii_strtoll (dent->d_name + strlen (binfile_prefix)+1,
+ NULL, 10);
+ g_assert (version > 0);
+
+ if (version > best_version)
+ {
+ best_version = version;
+ g_free (best_policy);
+ best_policy = g_strdup (dent->d_name);
+ }
+ }
+ }
+ }
+
+ if (!best_policy)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Could not find binary policy file");
+ goto out;
+ }
+
+ *out_csum = ot_checksum_file_at (bindir_dfd, best_policy, G_CHECKSUM_SHA256,
+ cancellable, error);
+ if (*out_csum == NULL)
+ goto out;
+
+ ret = TRUE;
+out:
+ return ret;
+}
+
+#endif
+
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
@@ -257,6 +346,12 @@ initable_init (GInitable *initable,
freecon (con);
}
+ if (!get_policy_checksum (&self->selinux_policy_csum, cancellable, error))
+ {
+ g_prefix_error (error, "While calculating SELinux checksum: ");
+ goto out;
+ }
+
self->selinux_policy_name = g_strdup (policytype);
self->selinux_policy_root = g_object_ref (etc_selinux_dir);
}
@@ -306,6 +401,12 @@ ostree_sepolicy_get_path (OstreeSePolicy *self)
return self->path;
}
+/**
+ * ostree_sepolicy_get_name:
+ * @self:
+ *
+ * Returns: (transfer none): Type of current policy
+ */
const char *
ostree_sepolicy_get_name (OstreeSePolicy *self)
{
@@ -317,6 +418,22 @@ ostree_sepolicy_get_name (OstreeSePolicy *self)
}
/**
+ * ostree_sepolicy_get_csum:
+ * @self:
+ *
+ * Returns: (transfer none): Checksum of current policy
+ */
+const char *
+ostree_sepolicy_get_csum (OstreeSePolicy *self)
+{
+#ifdef HAVE_SELINUX
+ return self->selinux_policy_csum;
+#else
+ return NULL;
+#endif
+}
+
+/**
* ostree_sepolicy_get_label:
* @self: Self
* @relpath: Path
diff --git a/src/libostree/ostree-sepolicy.h b/src/libostree/ostree-sepolicy.h
index 83e3b37..d204953 100644
--- a/src/libostree/ostree-sepolicy.h
+++ b/src/libostree/ostree-sepolicy.h
@@ -45,6 +45,9 @@ _OSTREE_PUBLIC
const char *ostree_sepolicy_get_name (OstreeSePolicy *self);
_OSTREE_PUBLIC
+const char *ostree_sepolicy_get_csum (OstreeSePolicy *self);
+
+_OSTREE_PUBLIC
gboolean ostree_sepolicy_get_label (OstreeSePolicy *self,
const char *relpath,
guint32 unix_mode,
diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c
index b2aaf32..8d30bdc 100644
--- a/src/libotutil/ot-checksum-utils.c
+++ b/src/libotutil/ot-checksum-utils.c
@@ -140,17 +140,17 @@ ot_gio_checksum_stream (GInputStream *in,
}
char *
-ot_checksum_file (GFile *file,
- GChecksumType checksum_type,
- GCancellable *cancellable,
- GError **error)
+ot_checksum_file_at (int dfd,
+ const char *path,
+ GChecksumType checksum_type,
+ GCancellable *cancellable,
+ GError **error)
{
GChecksum *checksum = NULL;
char *ret = NULL;
g_autoptr(GInputStream) in = NULL;
- in = (GInputStream*)g_file_read (file, cancellable, error);
- if (!in)
+ if (!ot_openat_read_stream (dfd, path, TRUE, &in, cancellable, error))
goto out;
checksum = g_checksum_new (checksum_type);
diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h
index eb8bbc0..8b3a394 100644
--- a/src/libotutil/ot-checksum-utils.h
+++ b/src/libotutil/ot-checksum-utils.h
@@ -53,10 +53,11 @@ gboolean ot_gio_checksum_stream (GInputStream *in,
GCancellable *cancellable,
GError **error);
-char * ot_checksum_file (GFile *file,
- GChecksumType checksum_type,
- GCancellable *cancellable,
- GError **error);
+char * ot_checksum_file_at (int dfd,
+ const char *path,
+ GChecksumType checksum_type,
+ GCancellable *cancellable,
+ GError **error);
void ot_gio_checksum_stream_async (GInputStream *in,
int io_priority,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]