--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "conf-files.h"
+#include "copy.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "ipe-setup.h"
+#include "nulstr-util.h"
+#include "path-util.h"
+
+#define IPE_SECFS_DIR "/sys/kernel/security/ipe"
+#define IPE_SECFS_NEW_POLICY IPE_SECFS_DIR "/new_policy"
+#define IPE_SECFS_POLICIES IPE_SECFS_DIR "/policies/"
+
+int ipe_setup(void) {
+#if ENABLE_IPE
+ _cleanup_strv_free_ char **policies = NULL;
+ int r;
+
+ /* Very quick smoke tests first: this is in the citical, sequential boot path, and in most cases it
+ * is unlikely this will be configured, so do the fastest existence checks first and immediately
+ * return if there's nothing to do. */
+
+ if (access(IPE_SECFS_DIR, F_OK) < 0) {
+ log_debug_errno(errno, "IPE support is disabled in the kernel, ignoring: %m");
+ return 0;
+ }
+
+ r = conf_files_list_nulstr(
+ &policies,
+ ".p7b",
+ /* root= */ NULL,
+ CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED,
+ CONF_PATHS_NULSTR("ipe"));
+ if (r < 0)
+ return log_error_errno(r, "Failed to assemble list of IPE policies: %m");
+
+ STRV_FOREACH(policy, policies) {
+ _cleanup_free_ char *policy_name = NULL, *file_name = NULL, *output_path = NULL, *activate_path = NULL;
+ _cleanup_close_ int input = -EBADF, output = -EBADF;
+ const char *suffix;
+
+ r = path_extract_filename(*policy, &file_name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract filename from IPE policy path %s: %m", *policy);
+
+ /* Filtered by conf_files_list_nulstr() */
+ suffix = ASSERT_PTR(endswith(file_name, ".p7b"));
+
+ policy_name = strndup(file_name, suffix - file_name);
+ if (!policy_name)
+ return log_oom();
+
+ if (!filename_is_valid(policy_name))
+ return log_error_errno(
+ SYNTHETIC_ERRNO(EINVAL),
+ "Invalid IPE policy name %s",
+ policy_name);
+
+ input = open(*policy, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
+ if (input < 0)
+ return log_error_errno(
+ errno,
+ "Failed to open the IPE policy file %s: %m",
+ *policy);
+
+ /* If policy is already installed, try to update it */
+ output_path = path_join(IPE_SECFS_POLICIES, policy_name, "update");
+ if (!output_path)
+ return log_oom();
+
+ output = open(output_path, O_WRONLY|O_CLOEXEC);
+ if (output < 0 && errno == ENOENT)
+ /* Policy is not installed, install it and activate it */
+ output = open(IPE_SECFS_NEW_POLICY, O_WRONLY|O_CLOEXEC);
+ if (output < 0)
+ return log_error_errno(
+ errno,
+ "Failed to open the IPE policy handle for writing: %m");
+
+ /* The policy is inline signed in binary format, so it has to be copied in one go, otherwise the
+ * kernel will reject partial inputs with -EBADMSG. */
+ r = copy_bytes(input, output, UINT64_MAX, /* copy_flags= */ 0);
+ if (r < 0)
+ return log_error_errno(
+ r,
+ "Failed to copy the IPE policy %s to %s: %m",
+ *policy,
+ output_path);
+
+ output = safe_close(output);
+
+ activate_path = path_join(IPE_SECFS_POLICIES, policy_name, "active");
+ if (!activate_path)
+ return log_oom();
+
+ r = write_string_file(activate_path, "1", WRITE_STRING_FILE_DISABLE_BUFFER);
+ if (r == -ESTALE) {
+ log_debug_errno(r,
+ "IPE policy %s is already loaded with a version that is equal or higher, skipping.",
+ policy_name);
+ continue;
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to activate the IPE policy %s: %m", policy_name);
+
+ log_info("Successfully loaded and activated the IPE policy %s.", policy_name);
+ }
+
+#endif /* ENABLE_IPE */
+ return 0;
+}