From 6760dcea53daa627e5147282109b854161a2efc4 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Sat, 8 Jun 2024 03:11:20 +0800 Subject: [PATCH] Add some IMA setup tools Resolves: https://issues.redhat.com/browse/RHEL-33751 Conflict: Upstream has -libs subpackage Upstream Status: https://src.fedoraproject.org/rpms/ima-evm-utils.git commit 8980421a049c776e2b77e534793aafb925b3ad48 Author: Coiby Xu Date: Mon May 6 17:48:52 2024 +0800 Add some IMA setup tools Some IMA setup tools are added to ease IMA setup which will do the following tasks, - add IMA signatures to installed packages files - load IMA keys and policy - enable the dracut integrity module to load IMA keys and policy automatically Two IMA polices as suggested by Stefan Berger are also provided which will be signed automatically with other package files. Thanks to Marko Myllynen for coming up with the idea to have a tool similar to fips-mode-setup. And thanks to Mimi Zohar and Stefan Berger for providing the feedback! Signed-off-by: Coiby Xu Signed-off-by: Coiby Xu --- dracut-98-integrity.conf | 1 + ima-add-sigs.sh | 82 ++++++++++++ ima-evm-utils.spec | 32 ++++- ima-setup.sh | 118 ++++++++++++++++++ ...01-appraise-exectuables-and-lib-signatures | 2 + policy-02-keylime-remote-attestation | 37 ++++++ policy_list | 2 + 7 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 dracut-98-integrity.conf create mode 100755 ima-add-sigs.sh create mode 100755 ima-setup.sh create mode 100644 policy-01-appraise-exectuables-and-lib-signatures create mode 100644 policy-02-keylime-remote-attestation create mode 100644 policy_list diff --git a/dracut-98-integrity.conf b/dracut-98-integrity.conf new file mode 100644 index 0000000..0996b9a --- /dev/null +++ b/dracut-98-integrity.conf @@ -0,0 +1 @@ +add_dracutmodules+=" integrity " diff --git a/ima-add-sigs.sh b/ima-add-sigs.sh new file mode 100755 index 0000000..eadd629 --- /dev/null +++ b/ima-add-sigs.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# This script add IMA signatures to installed RPM package files +# Usage: add_ima_sigs.sh [[ALL|PACKAGE_NAME] IMA_CERT_PATH] +# +# By default, it will add IMA sigantures to all installed package files. Or you +# can provide a package name to only add IMA signature for files of specicifed +# package. If it detects >=20 packages (or 1 package if you specify a package +# name) missing signatures in the RPM database, it will reinstall the packages +# in order to get the IMA signatures. +# +# With the signing IMA cert path specified, it will also try to verify +# the added IMA signature. + +if [[ -z "$1" || $1 == ALL ]]; then + package="--all" +else + package=$1 +fi + +ima_cert=$2 + +abort() { + echo "$1" + exit 1 +} + +# Add IMA signatures from RPM database +add_from_rpm_db() { + if ! command -v setfattr &>/dev/null; then + abort "Please install attr" + fi + + # use "|" as deliminator since it won't be used in a filename or signature + while IFS="|" read -r path sig; do + # [[ -z "$sig" ]] somehow doesn't work for some files that don't have IMA + # signatures. This may be a issue of rpm + if [[ "$sig" != "0"* ]]; then + continue + fi + + # Skip directory, soft links, non-existent files and vfat fs + if [[ -d "$path" || -L "$path" || ! -f "$path" || "$path" == "/boot/efi/EFI/"* ]]; then + continue + fi + + if ! setfattr -n security.ima "$path" -v "0x$sig"; then + echo "Failed to add IMA sig for $path" + fi + + [[ -e "$ima_cert" ]] || continue + # TODO + # don't verify the modified files like /etc? + if ! evmctl ima_verify -k "$ima_cert" "$path" &>/dev/null; then + echo "Failed to verify $path" + fi + done < <(rpm -q --queryformat "[%{FILENAMES}|%{FILESIGNATURES}\n]" "$package") +} + +# Add IMA signatures by reinstalling all packages +add_by_reinstall() { + [[ $package == "--all" ]] && package='*' + dnf reinstall "$package" -yq >/dev/null +} + +if [[ $package == "--all" ]]; then + reinstall_threshold=20 +else + if ! rpm -q --quiet $package; then + dnf install "$package" -yq >/dev/null + exit 0 + fi + reinstall_threshold=1 +fi + +unsigned_packages_in_rpm_db=$(rpm -q --queryformat "%{SIGPGP:pgpsig}\n" $package | grep "^(none)$" | wc -l) + +if [[ $unsigned_packages_in_rpm_db -ge $reinstall_threshold ]]; then + add_by_reinstall +else + add_from_rpm_db +fi diff --git a/ima-evm-utils.spec b/ima-evm-utils.spec index ffbc713..f9a1951 100644 --- a/ima-evm-utils.spec +++ b/ima-evm-utils.spec @@ -14,6 +14,14 @@ License: GPLv2 Url: http://linux-ima.sourceforge.net/ Source0: https://github.com/mimizohar/ima-evm-utils/releases/download/v%{version}/%{name}-%{version}.tar.gz +# IMA setup tools +Source2: dracut-98-integrity.conf +Source3: ima-add-sigs.sh +Source4: ima-setup.sh +Source100: policy-01-appraise-exectuables-and-lib-signatures +Source101: policy-02-keylime-remote-attestation +Source200: policy_list + %if 0%{bootstrap} # compat source and patches Source10: ima-evm-utils-1.4.tar.gz @@ -29,6 +37,9 @@ BuildRequires: libxslt BuildRequires: make BuildRequires: openssl-devel BuildRequires: tpm2-tss-devel +Requires: rpm-plugin-ima +Requires: keyutils +Requires: attr %description The Trusted Computing Group(TCG) run-time Integrity Measurement Architecture @@ -81,13 +92,32 @@ popd %ldconfig_scriptlets +# IMA setup tools +install -D -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_datadir}/ima/dracut-98-integrity.conf + +mkdir -p -m 755 $RPM_BUILD_ROOT%{_datadir}/ima/policies +while IFS= read -r policy_file +do + install -m 644 %{_sourcedir}/policy-"$policy_file" $RPM_BUILD_ROOT%{_datadir}/ima/policies/"$policy_file" +done < %{SOURCE200} + +install -D %{SOURCE3} $RPM_BUILD_ROOT%{_bindir}/ima-add-sigs +install -D %{SOURCE4} $RPM_BUILD_ROOT%{_bindir}/ima-setup + %files %license COPYING %doc NEWS README AUTHORS %{_bindir}/evmctl +%{_mandir}/man1/evmctl* + +# IMA setup tools +%{_datadir}/ima/policies +%{_datadir}/ima/dracut-98-integrity.conf +%{_bindir}/ima-add-sigs +%{_bindir}/ima-setup + # if you need to bump the soname version, coordinate with dependent packages %{_libdir}/libimaevm.so.4* -%{_mandir}/man1/evmctl* %if 0%{bootstrap} %{_libdir}/libimaevm.so.%{compat_soversion} %{_libdir}/libimaevm.so.%{compat_soversion}.0.0 diff --git a/ima-setup.sh b/ima-setup.sh new file mode 100755 index 0000000..6816d7d --- /dev/null +++ b/ima-setup.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# +# This script helps set up IMA. +# +IMA_SYSTEMD_POLICY=/etc/ima/ima-policy +IMA_POLICY_SYSFS=/sys/kernel/security/ima/policy + +usage() { + echo "Set up IMA." + cat </dev/null; then + echo "Failed to load IMA key ${i}" + else + _key_loaded=yes + fi + done + + if [[ $_key_loaded != yes ]]; then + echo "No IMA key loaded" + exit 1 + fi +} + +load_ima_policy() { + local ima_policy_path + + ima_policy_path=$1 + + if ! test -f "$ima_policy_path"; then + echo "$ima_policy_path doesn't exist" + return 1 + fi + if ! echo "$ima_policy_path" >"$IMA_POLICY_SYSFS"; then + echo "$ima_policy_path can't be loaded" + return 1 + fi + # Let systemd load the IMA policy which will load LSM rules first so IMA + # policy containing rules like "appraise obj_type=ifconfig_exec_t" can be + # loaded + [[ -e /etc/ima ]] || mkdir -p /etc/ima/ + if ! cp --preserve=xattr "$ima_policy_path" "$IMA_SYSTEMD_POLICY"; then + echo "Failed to copy $ima_policy_path to $IMA_SYSTEMD_POLICY" + return 1 + fi +} + +echo "Loading IMA keys" +load_ima_keys + +# Include the dracut integrity module to load the IMA keys and policy +# automatically when there is a system reboot +if ! lsinitrd --mod | grep -q integrity; then + cp --preserve=xattr /usr/share/ima/dracut-98-integrity.conf /etc/dracut.conf.d/98-integrity.conf + echo "Rebuilding the initramfs of kernel-$(uname -r) to include the dracut integrity module" + dracut -f +fi + +if ! load_ima_policy "$ima_policy_path"; then + echo "Failed to load IMA policy $ima_policy_path!" + exit 1 +fi diff --git a/policy-01-appraise-exectuables-and-lib-signatures b/policy-01-appraise-exectuables-and-lib-signatures new file mode 100644 index 0000000..afc4530 --- /dev/null +++ b/policy-01-appraise-exectuables-and-lib-signatures @@ -0,0 +1,2 @@ +appraise func=MMAP_CHECK mask=MAY_EXEC appraise_type=imasig +appraise func=BPRM_CHECK appraise_type=imasig diff --git a/policy-02-keylime-remote-attestation b/policy-02-keylime-remote-attestation new file mode 100644 index 0000000..5210734 --- /dev/null +++ b/policy-02-keylime-remote-attestation @@ -0,0 +1,37 @@ +# PROC_SUPER_MAGIC +dont_measure fsmagic=0x9fa0 +# SYSFS_MAGIC +dont_measure fsmagic=0x62656572 +# DEBUGFS_MAGIC +dont_measure fsmagic=0x64626720 +# TMPFS_MAGIC +dont_measure fsmagic=0x01021994 +# DEVPTS_SUPER_MAGIC +dont_measure fsmagic=0x1cd1 +# BINFMTFS_MAGIC +dont_measure fsmagic=0x42494e4d +# SECURITYFS_MAGIC +dont_measure fsmagic=0x73636673 +# SELINUX_MAGIC +dont_measure fsmagic=0xf97cff8c +# SMACK_MAGIC +dont_measure fsmagic=0x43415d53 +# CGROUP_SUPER_MAGIC +dont_measure fsmagic=0x27e0eb +# CGROUP2_SUPER_MAGIC +dont_measure fsmagic=0x63677270 +# NSFS_MAGIC +dont_measure fsmagic=0x6e736673 +# EFIVARFS_MAGIC +dont_measure fsmagic=0xde5e81e4 +# OVERLAYFS_MAGIC +# when containers are used we almost always want to ignore them +dont_measure fsmagic=0x794c7630 + + +# Measure and log keys loaded onto the .ima keyring +measure func=KEY_CHECK keyrings=.ima +# Measure and log executables +measure func=BPRM_CHECK +# Measure and log shared libraries +measure func=FILE_MMAP mask=MAY_EXEC diff --git a/policy_list b/policy_list new file mode 100644 index 0000000..23ff71a --- /dev/null +++ b/policy_list @@ -0,0 +1,2 @@ +01-appraise-exectuables-and-lib-signatures +02-keylime-remote-attestation