mirror of
https://github.com/ostreedev/ostree.git
synced 2025-03-19 22:50:35 +03:00
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
This commit is contained in:
parent
456f515522
commit
b7a04d51f8
@ -331,4 +331,5 @@ global:
|
||||
LIBOSTREE_2016.5 {
|
||||
global:
|
||||
ostree_repo_import_object_from_with_trust;
|
||||
ostree_sepolicy_get_csum;
|
||||
} LIBOSTREE_2016.4;
|
||||
|
@ -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)
|
||||
{
|
||||
@ -316,6 +417,22 @@ ostree_sepolicy_get_name (OstreeSePolicy *self)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -44,6 +44,9 @@ GFile * ostree_sepolicy_get_path (OstreeSePolicy *self);
|
||||
_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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user