summaryrefslogtreecommitdiff
path: root/src/libostree/ostree-repo-verity.c
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2021-01-07 21:17:01 +0000
committerColin Walters <walters@verbum.org>2021-01-11 14:36:40 +0000
commit441233b51c86c252533923835aedcf2ca1972f78 (patch)
treeee7e384bf5c20b4befac7eda156a45f6ae5acadd /src/libostree/ostree-repo-verity.c
parent0b90f1f9a84bbd830e4e56b1d3a43bdf04e405ce (diff)
downloadostree-441233b51c86c252533923835aedcf2ca1972f78.tar.gz
repo: Move fsverity bits to ostree-repo-verity.c
This file will get larger when we start doing more with fsverity.
Diffstat (limited to 'src/libostree/ostree-repo-verity.c')
-rw-r--r--src/libostree/ostree-repo-verity.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/libostree/ostree-repo-verity.c b/src/libostree/ostree-repo-verity.c
new file mode 100644
index 00000000..92b026ee
--- /dev/null
+++ b/src/libostree/ostree-repo-verity.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: LGPL-2.0+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <sys/ioctl.h>
+
+#include "ostree-core-private.h"
+#include "ostree-repo-private.h"
+#include "otutil.h"
+#include "ot-fs-utils.h"
+#ifdef HAVE_LINUX_FSVERITY_H
+#include <linux/fsverity.h>
+#endif
+
+gboolean
+_ostree_repo_parse_fsverity_config (OstreeRepo *self, GError **error)
+{
+ /* Currently experimental */
+ static const char fsverity_key[] = "ex-fsverity";
+ self->fs_verity_wanted = _OSTREE_FEATURE_NO;
+#ifdef HAVE_LINUX_FSVERITY_H
+ self->fs_verity_supported = _OSTREE_FEATURE_MAYBE;
+#else
+ self->fs_verity_supported = _OSTREE_FEATURE_NO;
+#endif
+ gboolean fsverity_required = FALSE;
+ if (!ot_keyfile_get_boolean_with_default (self->config, fsverity_key, "required",
+ FALSE, &fsverity_required, error))
+ return FALSE;
+ if (fsverity_required)
+ {
+ self->fs_verity_wanted = _OSTREE_FEATURE_YES;
+ if (self->fs_verity_supported == _OSTREE_FEATURE_NO)
+ return glnx_throw (error, "fsverity required, but libostree compiled without support");
+ }
+ else
+ {
+ gboolean fsverity_opportunistic = FALSE;
+ if (!ot_keyfile_get_boolean_with_default (self->config, fsverity_key, "opportunistic",
+ FALSE, &fsverity_opportunistic, error))
+ return FALSE;
+ if (fsverity_opportunistic)
+ self->fs_verity_wanted = _OSTREE_FEATURE_MAYBE;
+ }
+
+ return TRUE;
+}
+
+
+/* Wrapper around the fsverity ioctl, compressing the result to
+ * "success, unsupported or error". This is used for /boot where
+ * we enable verity if supported.
+ * */
+gboolean
+_ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf,
+ _OstreeFeatureSupport fsverity_requested,
+ gboolean *supported,
+ GError **error)
+{
+ /* Set this by default to simplify the code below */
+ if (supported)
+ *supported = FALSE;
+
+ if (fsverity_requested == _OSTREE_FEATURE_NO)
+ return TRUE;
+
+#ifdef HAVE_LINUX_FSVERITY_H
+ GLNX_AUTO_PREFIX_ERROR ("fsverity", error);
+
+ /* fs-verity requires a read-only file descriptor */
+ if (!glnx_tmpfile_reopen_rdonly (tmpf, error))
+ return FALSE;
+
+ struct fsverity_enable_arg arg = { 0, };
+ arg.version = 1;
+ arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256; /* TODO configurable? */
+ arg.block_size = 4096; /* FIXME query */
+ arg.salt_size = 0; /* TODO store salt in ostree repo config */
+ arg.salt_ptr = 0;
+ arg.sig_size = 0; /* We don't currently expect use of in-kernel signature verification */
+ arg.sig_ptr = 0;
+
+ if (ioctl (tmpf->fd, FS_IOC_ENABLE_VERITY, &arg) < 0)
+ {
+ switch (errno)
+ {
+ case ENOTTY:
+ case EOPNOTSUPP:
+ return TRUE;
+ default:
+ return glnx_throw_errno_prefix (error, "ioctl(FS_IOC_ENABLE_VERITY)");
+ }
+ }
+
+ if (supported)
+ *supported = TRUE;
+#endif
+ return TRUE;
+}
+
+/* Enable verity on a file, respecting the "wanted" and "supported" states.
+ * The main idea here is to optimize out pointlessly calling the ioctl()
+ * over and over in cases where it's not supported for the repo's filesystem,
+ * as well as to support "opportunistic" use (requested and if filesystem supports).
+ * */
+gboolean
+_ostree_tmpf_fsverity (OstreeRepo *self,
+ GLnxTmpfile *tmpf,
+ GError **error)
+{
+#ifdef HAVE_LINUX_FSVERITY_H
+ g_mutex_lock (&self->txn_lock);
+ _OstreeFeatureSupport fsverity_wanted = self->fs_verity_wanted;
+ _OstreeFeatureSupport fsverity_supported = self->fs_verity_supported;
+ g_mutex_unlock (&self->txn_lock);
+
+ switch (fsverity_wanted)
+ {
+ case _OSTREE_FEATURE_YES:
+ {
+ if (fsverity_supported == _OSTREE_FEATURE_NO)
+ return glnx_throw (error, "fsverity required but filesystem does not support it");
+ }
+ break;
+ case _OSTREE_FEATURE_MAYBE:
+ break;
+ case _OSTREE_FEATURE_NO:
+ return TRUE;
+ }
+
+ gboolean supported = FALSE;
+ if (!_ostree_tmpf_fsverity_core (tmpf, fsverity_wanted, &supported, error))
+ return FALSE;
+
+ if (!supported)
+ {
+ if (G_UNLIKELY (fsverity_wanted == _OSTREE_FEATURE_YES))
+ return glnx_throw (error, "fsverity required but filesystem does not support it");
+
+ /* If we got here, we must be trying "opportunistic" use of fs-verity */
+ g_assert_cmpint (fsverity_wanted, ==, _OSTREE_FEATURE_MAYBE);
+ g_mutex_lock (&self->txn_lock);
+ self->fs_verity_supported = _OSTREE_FEATURE_NO;
+ g_mutex_unlock (&self->txn_lock);
+ return TRUE;
+ }
+
+ g_mutex_lock (&self->txn_lock);
+ self->fs_verity_supported = _OSTREE_FEATURE_YES;
+ g_mutex_unlock (&self->txn_lock);
+#else
+ g_assert_cmpint (self->fs_verity_wanted, !=, _OSTREE_FEATURE_YES);
+#endif
+ return TRUE;
+}