mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
core: load IPE policy on boot
IPE is a new LSM being introduced in 6.12. Like IMA, it works based on a policy file that has to be loaded at boot, the earlier the better. So like IMA, if such a policy is present, load it and activate it. If there are any .p7b files in /etc/ipe/, load them as policies. The files have to be inline signed in DER format as per IPE documentation. For more information on the details of IPE: https://microsoft.github.io/ipe/
This commit is contained in:
parent
3cb93ebcf2
commit
394c61416c
@ -1661,6 +1661,7 @@ foreach term : ['analyze',
|
||||
'hwdb',
|
||||
'idn',
|
||||
'ima',
|
||||
'ipe',
|
||||
'initrd',
|
||||
'kernel-install',
|
||||
'ldconfig',
|
||||
|
@ -388,6 +388,8 @@ option('polkit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' :
|
||||
description : 'polkit support')
|
||||
option('ima', type : 'boolean',
|
||||
description : 'IMA support')
|
||||
option('ipe', type : 'boolean',
|
||||
description : 'IPE support')
|
||||
|
||||
option('acl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
description : 'libacl support')
|
||||
|
@ -45,6 +45,12 @@ const char* const systemd_features =
|
||||
" -IMA"
|
||||
#endif
|
||||
|
||||
#if ENABLE_IMA
|
||||
" +IPE"
|
||||
#else
|
||||
" -IPE"
|
||||
#endif
|
||||
|
||||
#if ENABLE_SMACK
|
||||
" +SMACK"
|
||||
#else
|
||||
|
112
src/core/ipe-setup.c
Normal file
112
src/core/ipe-setup.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* 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;
|
||||
}
|
4
src/core/ipe-setup.h
Normal file
4
src/core/ipe-setup.h
Normal file
@ -0,0 +1,4 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
int ipe_setup(void);
|
@ -57,6 +57,7 @@
|
||||
#include "ima-setup.h"
|
||||
#include "import-creds.h"
|
||||
#include "initrd-util.h"
|
||||
#include "ipe-setup.h"
|
||||
#include "killall.h"
|
||||
#include "kmod-setup.h"
|
||||
#include "limits-util.h"
|
||||
@ -2920,6 +2921,12 @@ static int initialize_security(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = ipe_setup();
|
||||
if (r < 0) {
|
||||
*ret_error_message = "Failed to load IPE policy";
|
||||
return r;
|
||||
}
|
||||
|
||||
dual_timestamp_now(security_finish_timestamp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ systemd_sources = files(
|
||||
'kmod-setup.c',
|
||||
'apparmor-setup.c',
|
||||
'ima-setup.c',
|
||||
'ipe-setup.c',
|
||||
'selinux-setup.c',
|
||||
'smack-setup.c',
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user