#!/bin/sh # Initramfs script for IMA initialzation # # This script is a halper used to load the external # IMA policy and certificate used to verify the IMA # signature. # # Copyright (c) 2017, Jia Zhang # All rights reserved. # # See "LICENSE" for license terms. # Exit code: # 0 - IMA initialiazation complete # 1 - Kernel doesn't support securityfs # 2 - Kernel doesn't support IMA # 3 - There is no IMA certificate to load # 4 - There is no IMA policy file defined # 5 - Unable to load IMA policy file # If root directory is not specified, the root of # initramfs assumed. ROOT_DIR="${1}" SECURITYFS_DIR="${ROOT_DIR}/sys/kernel/security" # The policy files are always placed in initramfs IMA_POLICY=/etc/ima/ima_policy SECURITYFS_MOUNTED=0 print_critical() { printf "\033[1;35m" echo "$@" printf "\033[0m" } print_error() { printf "\033[1;31m" echo "$@" printf "\033[0m" } print_warning() { printf "\033[1;33m" echo "$@" printf "\033[0m" } print_info() { printf "\033[1;32m" echo "$@" printf "\033[0m" } print_verbose() { printf "\033[1;36m" echo "$@" printf "\033[0m" } trap_handler() { local err=$? print_verbose "Cleaning up with exit code $err ..." [ $SECURITYFS_MOUNTED -eq 1 ] && umount "$SECURITYFS_DIR" 2>"${ROOT_DIR}/dev/null" } trap "trap_handler $?" SIGINT EXIT if grep -q "ima_appraise=off" "${ROOT_DIR}/proc/cmdline"; then print_info "Skip to load the IMA certificate and policy" exit 0 fi if ! grep -q securityfs "${ROOT_DIR}/proc/mounts"; then ! mount -t securityfs none "$SECURITYFS_DIR" 2>"${ROOT_DIR}/dev/null" && { print_error "Unable to mount securityfs filesystem" exit 1 } SECURITYFS_MOUNTED=1 securityfs_dir="$SECURITYFS_DIR" else securityfs_dirs="$(grep securityfs ${ROOT_DIR}/proc/mounts | awk '{print $2}')" # Use the first one. for securityfs_dir in "$securityfs_dirs"; do break done fi [ ! -d "$securityfs_dir/ima" ] && print_info "IMA is not enabled. Exiting ..." && exit 2 mount --move ${ROOT_DIR}/proc /proc # If we have a secondary trusted keyring, here is the opportunity to load # additional trusted keys from the real rootfs. for cert in ${ROOT_DIR}/etc/keys/x509_secondary_*.der; do [ ! -s "$cert" ] && continue name=`basename $cert` if ! keyctl padd asymmetric "$name" %:.secondary_trusted_keys < $cert > ${ROOT_DIR}/dev/null; then print_critical "Unable to load the secondary certificate $cert" else print_verbose "The secondary certificate $cert has been loaded" fi done # The trusted IMA certificate /etc/keys/x509_ima.der in initramfs was # automatically loaded by kernel already. Here is the opportunity to load # a custom IMA certificate from the real rootfs. for cert in ${ROOT_DIR}/etc/keys/x509_ima*.der; do [ ! -s "$cert" ] && continue name=`basename $cert` if ! keyctl padd asymmetric "$name" %:.ima < $cert > ${ROOT_DIR}/dev/null; then print_critical "Unable to load the custom IMA certificate $cert for IMA appraisal" else print_verbose "The custom IMA certificate $cert loaded for IMA appraisal" fi done mount --move /proc ${ROOT_DIR}/proc # Attempt to load the default policy. [ ! -s "${IMA_POLICY}" ] && IMA_POLICY="${IMA_POLICY}.default" [ ! -s "${IMA_POLICY}" ] && { print_warning "No IMA policy file defined" exit 4 } echo "${IMA_POLICY}" > "$securityfs_dir/ima/policy" && { # Attempt to load IMA policies from the real rootfs. for policy in ${ROOT_DIR}/etc/ima/ima_policy*; do if [ -s "$policy" ]; then "${ROOT_DIR}/bin/echo.coreutils" "$policy" > "$securityfs_dir/ima/policy" fi done exit 0 } || { print_critical "Unable to load the IMA policy ${IMA_POLICY}" exit 5 }