diff --git a/.gitignore b/.gitignore index be3fbc7..734df2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -SOURCES/ima-evm-utils-1.3.2.tar.gz -SOURCES/ima-evm-utils-1.4.tar.gz +SOURCES/centosimarelease-9.der +SOURCES/ima-evm-utils-1.5.tar.gz +SOURCES/redhatimarelease-9.der diff --git a/.ima-evm-utils.metadata b/.ima-evm-utils.metadata index 52cee1d..9c5d0f7 100644 --- a/.ima-evm-utils.metadata +++ b/.ima-evm-utils.metadata @@ -1,2 +1,3 @@ -034d163533ae5f9c06001b375ec7e5a1b09a3853 SOURCES/ima-evm-utils-1.3.2.tar.gz -f23d8a406759a469b0223b0bfb302ada4407a1d1 SOURCES/ima-evm-utils-1.4.tar.gz +61d5a223ff0c79189505abae77e0087c4b2d2b47 SOURCES/centosimarelease-9.der +87b19af821da481a50e820958f75104878442472 SOURCES/ima-evm-utils-1.5.tar.gz +99e571f9de4188f3b5fdf1f84ff73f6cc4bb6a0e SOURCES/redhatimarelease-9.der diff --git a/SOURCES/0001-evmctl-fix-memory-leak-in-get_password.patch b/SOURCES/0001-evmctl-fix-memory-leak-in-get_password.patch deleted file mode 100644 index e6657d1..0000000 --- a/SOURCES/0001-evmctl-fix-memory-leak-in-get_password.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2f1740eab432abc8e85172531d97eba33342474c Mon Sep 17 00:00:00 2001 -From: Bruno Meneguele -Date: Mon, 16 Aug 2021 12:11:15 -0300 -Subject: [PATCH] evmctl: fix memory leak in get_password - -The variable "password" is not freed nor returned in case get_password() -succeeds. Return it instead of the intermediary variable "pwd". Issue found -by Coverity scan tool. - -src/evmctl.c:2565: leaked_storage: Variable "password" going out of scope - leaks the storage it points to. - -Signed-off-by: Bruno Meneguele ---- - src/evmctl.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/evmctl.c b/src/evmctl.c -index a8065bbe124a..ab7173723095 100644 ---- a/src/evmctl.c -+++ b/src/evmctl.c -@@ -2625,7 +2625,12 @@ static char *get_password(void) - return NULL; - } - -- return pwd; -+ if (pwd == NULL) { -+ free(password); -+ return NULL; -+ } -+ -+ return password; - } - - int main(int argc, char *argv[]) --- -2.31.1 - diff --git a/SOURCES/0001-libimaevm-make-SHA-256-the-default-hash-algorithm.patch b/SOURCES/0001-libimaevm-make-SHA-256-the-default-hash-algorithm.patch deleted file mode 100644 index e6dc92d..0000000 --- a/SOURCES/0001-libimaevm-make-SHA-256-the-default-hash-algorithm.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 916a0f97fd244a48fde429a63ddc04ed1ed94f8b Mon Sep 17 00:00:00 2001 -From: Bruno Meneguele -Date: Mon, 16 Aug 2021 17:58:35 -0300 -Subject: [PATCH] libimaevm: make SHA-256 the default hash algorithm - -The SHA-1 algorithm is considered a weak hash algorithm and there has been -some movement within certain distros to drop its support completely or at -least drop it from the default behavior. ima-evm-utils uses it as the -default algorithm in case the user doesn't explicitly ask for another -through the --hashalgo/-a option. With that, make SHA-256 the default hash -algorithm instead. - -Signed-off-by: Bruno Meneguele ---- - README | 2 +- - src/evmctl.c | 2 +- - src/libimaevm.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/README b/README -index 87cd3b5cd7da..0dc02f551673 100644 ---- a/README -+++ b/README -@@ -41,7 +41,7 @@ COMMANDS - OPTIONS - ------- - -- -a, --hashalgo sha1 (default), sha224, sha256, sha384, sha512 -+ -a, --hashalgo sha1, sha224, sha256 (default), sha384, sha512 - -s, --imasig make IMA signature - -d, --imahash make IMA hash - -f, --sigfile store IMA signature in .sig file instead of xattr -diff --git a/src/evmctl.c b/src/evmctl.c -index a8065bbe124a..e0e55bc0b122 100644 ---- a/src/evmctl.c -+++ b/src/evmctl.c -@@ -2496,7 +2496,7 @@ static void usage(void) - - printf( - "\n" -- " -a, --hashalgo sha1 (default), sha224, sha256, sha384, sha512, streebog256, streebog512\n" -+ " -a, --hashalgo sha1, sha224, sha256 (default), sha384, sha512, streebog256, streebog512\n" - " -s, --imasig make IMA signature\n" - " -d, --imahash make IMA hash\n" - " -f, --sigfile store IMA signature in .sig file instead of xattr\n" -diff --git a/src/libimaevm.c b/src/libimaevm.c -index 8e9615796153..f6c72b878d88 100644 ---- a/src/libimaevm.c -+++ b/src/libimaevm.c -@@ -88,7 +88,7 @@ static const char *const pkey_hash_algo_kern[PKEY_HASH__LAST] = { - struct libimaevm_params imaevm_params = { - .verbose = LOG_INFO, - .x509 = 1, -- .hash_algo = "sha1", -+ .hash_algo = "sha256", - }; - - static void __attribute__ ((constructor)) libinit(void); --- -2.31.1 - diff --git a/SOURCES/dracut-98-integrity.conf b/SOURCES/dracut-98-integrity.conf new file mode 100644 index 0000000..0996b9a --- /dev/null +++ b/SOURCES/dracut-98-integrity.conf @@ -0,0 +1 @@ +add_dracutmodules+=" integrity " diff --git a/SOURCES/ima-add-sigs.sh b/SOURCES/ima-add-sigs.sh new file mode 100755 index 0000000..4321ace --- /dev/null +++ b/SOURCES/ima-add-sigs.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# +# This script add IMA signatures to installed RPM package files +# Usage: add_ima_sigs.sh [--package=PACKAGE_NAME|ALL] [--ima-cert=IMA_CERT_PATH] [--reinstall_threshold=NUM] +# +# 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. + +for _opt in "$@"; do + case "$_opt" in + --reinstall_threshold=*) + reinstall_threshold=${_opt#*=} + ;; + --package=*) + package=${_opt#*=} + ;; + --ima_cert=*) + ima_cert=${_opt#*=} + ;; + *) + usage + ;; + esac +done + +if [[ -z $package ]] || [[ $package == ALL ]]; then + package="--all" +fi + +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 [[ -z $reinstall_threshold ]]; then + 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 +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/SOURCES/ima-setup.sh b/SOURCES/ima-setup.sh new file mode 100755 index 0000000..a997582 --- /dev/null +++ b/SOURCES/ima-setup.sh @@ -0,0 +1,141 @@ +#!/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 <reinstall_threshold packages in the RPM DB missing IMA signatures, reinstalling the packages to add IMA signatures to the packages. + By default, IMA sigatures will be obtained from the RPM DB. However the RPM DB may not have the signatures. Dectect this case by checking if there are >reinstall_threshold package missing IMA signatures. + +EOF + exit 1 +} + +for _opt in "$@"; do + case "$_opt" in + --policy=*) + ima_policy_path=${_opt#*=} + if [[ ! -e $ima_policy_path ]]; then + echo "$policy_file doesn't exist" + exit 1 + fi + ;; + --reinstall_threshold=*) + reinstall_threshold=${_opt#*=} + ;; + *) + usage + ;; + esac +done + +if [[ $# -eq 0 ]]; then + usage +fi + +echo "Installing prerequisite package rpm-plugin-ima" +if ! dnf install rpm-plugin-ima -yq; then + echo "Failed to install rpm-plugin-ima, abort" + exit 1 +fi + +# Add IMA signatures +if test -f /run/ostree-booted; then + echo "You are using OSTree, please enable IMA signatures as part of the OSTree creation process." +else + echo "Adding IMA signatures to installed package files" + if ! ima-add-sigs; then + echo "Failed to add IMA signatures, abort" + exit 1 + fi +fi + +load_ima_keys() { + local _key_loaded + + if line=$(keyctl describe %keyring:.ima); then + _ima_id=${line%%:*} + else + echo "Failed to get ID of the .ima keyring" + exit 1 + fi + + for i in /etc/keys/ima/*; do + if [ ! -f "${i}" ]; then + echo "No IMA key exist" + exit 1 + fi + + if ! evmctl import "${i}" "${_ima_id}" &>/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 + + if command -v grubby >/dev/null; then + _default_kernel=$(grubby --default-kernel | sed -En "s/.*vmlinuz-(.*)/\1/p") + if [[ $_default_kernel != $(uname -r) ]]; then + echo "Current kernel is not the default kernel ($_default_kernel), include dracut integrity for it as well" + dracut -f --kver "$_default_kernel" + fi + fi + +fi + +if ! load_ima_policy "$ima_policy_path"; then + echo "Failed to load IMA policy $ima_policy_path!" + exit 1 +fi diff --git a/SOURCES/policy-01-appraise-exectuables-and-lib-signatures b/SOURCES/policy-01-appraise-exectuables-and-lib-signatures new file mode 100644 index 0000000..afc4530 --- /dev/null +++ b/SOURCES/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/SOURCES/policy-02-keylime-remote-attestation b/SOURCES/policy-02-keylime-remote-attestation new file mode 100644 index 0000000..5210734 --- /dev/null +++ b/SOURCES/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/SOURCES/policy_list b/SOURCES/policy_list new file mode 100644 index 0000000..23ff71a --- /dev/null +++ b/SOURCES/policy_list @@ -0,0 +1,2 @@ +01-appraise-exectuables-and-lib-signatures +02-keylime-remote-attestation diff --git a/SPECS/ima-evm-utils.spec b/SPECS/ima-evm-utils.spec index 109c0bd..15330d4 100644 --- a/SPECS/ima-evm-utils.spec +++ b/SPECS/ima-evm-utils.spec @@ -1,31 +1,34 @@ -%bcond_with compat +# If the soname gets bumped we need to ship a compat library to be able +# to bootstrap and rebuild rpm else we end up with chicken and egg problem. +%global bootstrap 0 -# For cases where the soname requires a bump we need to define with_compat, -# update the package into the side-tag, update RPM (rpm-sign) into side-tag, -# _then_ undefine with_compat and rebuild the package into the side-tag. This -# is required to workaround the chiken-egg situation with the rpm-sign update. -# The compat pkg must not make the compose, it's only a buildrequirement for -# rpm-sign in a soname bump. -%if ! %{with compat} -%undefine with_compat -%endif - -%if %{with compat} -%global compat_soversion 2 +%if 0%{bootstrap} +%global compat_soversion 3 %endif Name: ima-evm-utils -Version: 1.4 -Release: 4%{?dist} +Version: 1.5 +Release: 2%{?dist} Summary: IMA/EVM support utilities License: GPLv2 Url: http://linux-ima.sourceforge.net/ -Source: http://sourceforge.net/projects/linux-ima/files/ima-evm-utils/%{name}-%{version}.tar.gz +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 +Source300: redhatimarelease-9.der +Source301: centosimarelease-9.der + + +%if 0%{bootstrap} # compat source and patches -Source10: ima-evm-utils-1.3.2.tar.gz -Patch10: 0001-evmctl-fix-memory-leak-in-get_password.patch -Patch11: 0001-libimaevm-make-SHA-256-the-default-hash-algorithm.patch +Source10: ima-evm-utils-1.4.tar.gz +%endif BuildRequires: asciidoc BuildRequires: autoconf @@ -37,6 +40,8 @@ BuildRequires: libxslt BuildRequires: make BuildRequires: openssl-devel BuildRequires: tpm2-tss-devel +Requires: keyutils +Requires: attr %description The Trusted Computing Group(TCG) run-time Integrity Measurement Architecture @@ -53,23 +58,14 @@ Requires: %{name} = %{version}-%{release} %description devel This package provides the header files for %{name} -%if %{with compat} -%package -n %{name}%{compat_soversion} -Summary: Compatibility package of %{name} - -%description -n %{name}%{compat_soversion} -This package provides the libimaevm.so.%{compat_soversion} relative to %{name}-1.3 -%endif - %prep %setup -q -%if %{with compat} +%if 0%{bootstrap} mkdir compat/ -tar -zxf %{SOURCE10} --strip-components=1 -C compat/ -cd compat/ -%patch10 -p1 -%patch11 -p1 +pushd compat/ +tar -zxf %{SOURCE10} --strip-components=1 +popd %endif %build @@ -77,10 +73,10 @@ autoreconf -vif %configure --disable-static %make_build -%if %{with compat} +%if 0%{bootstrap} pushd compat/ autoreconf -vif -%configure --disable-static +%configure --disable-static --disable-engine %make_build popd %endif @@ -89,7 +85,7 @@ popd %make_install find %{buildroot} -type f -name "*.la" -print -delete -%if %{with compat} +%if 0%{bootstrap} pushd compat/src/.libs/ install -p libimaevm.so.%{compat_soversion}.0.0 %{buildroot}%{_libdir}/libimaevm.so.%{compat_soversion}.0.0 ln -s -f %{buildroot}%{_libdir}/libimaevm.so.%{compat_soversion}.0.0 %{buildroot}%{_libdir}/libimaevm.so.%{compat_soversion} @@ -98,26 +94,59 @@ 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 + +# IMA code-signing certs +install -d -m 755 $RPM_BUILD_ROOT/etc/keys/ima +install -m 644 %{SOURCE300} %{SOURCE301} $RPM_BUILD_ROOT/etc/keys/ima/ + %files %license COPYING %doc NEWS README AUTHORS %{_bindir}/evmctl -# if you need to bump the soname version, coordinate with dependent packages -%{_libdir}/libimaevm.so.3* %{_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* +%if 0%{bootstrap} +%{_libdir}/libimaevm.so.%{compat_soversion} +%{_libdir}/libimaevm.so.%{compat_soversion}.0.0 +%endif + +# IMA code-signing certs +/etc/keys/ima/*.der + %files devel %{_pkgdocdir}/*.sh %{_includedir}/imaevm.h %{_libdir}/libimaevm.so -%if %{with compat} -%files -n %{name}%{compat_soversion} -%{_libdir}/libimaevm.so.%{compat_soversion} -%{_libdir}/libimaevm.so.%{compat_soversion}.0.0 -%endif - %changelog +* Fri Jun 07 2024 Coiby Xu - 1.5-2 +- add some IMA setup tools (RHEL-33751) + +* Tue Jun 04 2024 Coiby Xu - 1.5-1 +- Disable compat build (RHEL-2969) + +* Fri Apr 12 2024 Coiby Xu - 1.5-0.1 +- Update to upstream 1.5 (RHEL-2969) + * Mon Dec 13 2021 Bruno Meneguele - 1.4-4 - Fix compat bcond_with value check.