18c2ecf20Sopenharmony_ci#!/bin/sh
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci#
48c2ecf20Sopenharmony_ci# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ciVERBOSE="${VERBOSE:-1}"
78c2ecf20Sopenharmony_ciIKCONFIG="/tmp/config-`uname -r`"
88c2ecf20Sopenharmony_ciKERNEL_IMAGE="/boot/vmlinuz-`uname -r`"
98c2ecf20Sopenharmony_ciSECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}')
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cilog_info()
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "[INFO] $1"
148c2ecf20Sopenharmony_ci}
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci# The ksefltest framework requirement returns 0 for PASS.
178c2ecf20Sopenharmony_cilog_pass()
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1 [PASS]"
208c2ecf20Sopenharmony_ci	exit 0
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci# The ksefltest framework requirement returns 1 for FAIL.
248c2ecf20Sopenharmony_cilog_fail()
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1 [FAIL]"
278c2ecf20Sopenharmony_ci	exit 1
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci# The ksefltest framework requirement returns 4 for SKIP.
318c2ecf20Sopenharmony_cilog_skip()
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1"
348c2ecf20Sopenharmony_ci	exit 4
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
388c2ecf20Sopenharmony_ci# (Based on kdump-lib.sh)
398c2ecf20Sopenharmony_ciget_efivarfs_secureboot_mode()
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	local efivarfs="/sys/firmware/efi/efivars"
428c2ecf20Sopenharmony_ci	local secure_boot_file=""
438c2ecf20Sopenharmony_ci	local setup_mode_file=""
448c2ecf20Sopenharmony_ci	local secureboot_mode=0
458c2ecf20Sopenharmony_ci	local setup_mode=0
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	# Make sure that efivar_fs is mounted in the normal location
488c2ecf20Sopenharmony_ci	if ! grep -q "^\S\+ $efivarfs efivarfs" /proc/mounts; then
498c2ecf20Sopenharmony_ci		log_info "efivars is not mounted on $efivarfs"
508c2ecf20Sopenharmony_ci		return 0;
518c2ecf20Sopenharmony_ci	fi
528c2ecf20Sopenharmony_ci	secure_boot_file=$(find "$efivarfs" -name SecureBoot-* 2>/dev/null)
538c2ecf20Sopenharmony_ci	setup_mode_file=$(find "$efivarfs" -name SetupMode-* 2>/dev/null)
548c2ecf20Sopenharmony_ci	if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
558c2ecf20Sopenharmony_ci		secureboot_mode=$(hexdump -v -e '/1 "%d\ "' \
568c2ecf20Sopenharmony_ci			"$secure_boot_file"|cut -d' ' -f 5)
578c2ecf20Sopenharmony_ci		setup_mode=$(hexdump -v -e '/1 "%d\ "' \
588c2ecf20Sopenharmony_ci			"$setup_mode_file"|cut -d' ' -f 5)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci		if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then
618c2ecf20Sopenharmony_ci			log_info "secure boot mode enabled (CONFIG_EFIVAR_FS)"
628c2ecf20Sopenharmony_ci			return 1;
638c2ecf20Sopenharmony_ci		fi
648c2ecf20Sopenharmony_ci	fi
658c2ecf20Sopenharmony_ci	return 0;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciget_efi_var_secureboot_mode()
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	local efi_vars
718c2ecf20Sopenharmony_ci	local secure_boot_file
728c2ecf20Sopenharmony_ci	local setup_mode_file
738c2ecf20Sopenharmony_ci	local secureboot_mode
748c2ecf20Sopenharmony_ci	local setup_mode
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	if [ ! -d "$efi_vars" ]; then
778c2ecf20Sopenharmony_ci		log_skip "efi_vars is not enabled\n"
788c2ecf20Sopenharmony_ci	fi
798c2ecf20Sopenharmony_ci	secure_boot_file=$(find "$efi_vars" -name SecureBoot-* 2>/dev/null)
808c2ecf20Sopenharmony_ci	setup_mode_file=$(find "$efi_vars" -name SetupMode-* 2>/dev/null)
818c2ecf20Sopenharmony_ci	if [ -f "$secure_boot_file/data" ] && \
828c2ecf20Sopenharmony_ci	   [ -f "$setup_mode_file/data" ]; then
838c2ecf20Sopenharmony_ci		secureboot_mode=`od -An -t u1 "$secure_boot_file/data"`
848c2ecf20Sopenharmony_ci		setup_mode=`od -An -t u1 "$setup_mode_file/data"`
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then
878c2ecf20Sopenharmony_ci			log_info "secure boot mode enabled (CONFIG_EFI_VARS)"
888c2ecf20Sopenharmony_ci			return 1;
898c2ecf20Sopenharmony_ci		fi
908c2ecf20Sopenharmony_ci	fi
918c2ecf20Sopenharmony_ci	return 0;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
958c2ecf20Sopenharmony_ci# The secure boot mode can be accessed either as the last integer
968c2ecf20Sopenharmony_ci# of "od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-*" or from
978c2ecf20Sopenharmony_ci# "od -An -t u1 /sys/firmware/efi/vars/SecureBoot-*/data".  The efi
988c2ecf20Sopenharmony_ci# SetupMode can be similarly accessed.
998c2ecf20Sopenharmony_ci# Return 1 for SecureBoot mode enabled and SetupMode mode disabled.
1008c2ecf20Sopenharmony_ciget_secureboot_mode()
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	local secureboot_mode=0
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	get_efivarfs_secureboot_mode
1058c2ecf20Sopenharmony_ci	secureboot_mode=$?
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	# fallback to using the efi_var files
1088c2ecf20Sopenharmony_ci	if [ $secureboot_mode -eq 0 ]; then
1098c2ecf20Sopenharmony_ci		get_efi_var_secureboot_mode
1108c2ecf20Sopenharmony_ci		secureboot_mode=$?
1118c2ecf20Sopenharmony_ci	fi
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	if [ $secureboot_mode -eq 0 ]; then
1148c2ecf20Sopenharmony_ci		log_info "secure boot mode not enabled"
1158c2ecf20Sopenharmony_ci	fi
1168c2ecf20Sopenharmony_ci	return $secureboot_mode;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cirequire_root_privileges()
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	if [ $(id -ru) -ne 0 ]; then
1228c2ecf20Sopenharmony_ci		log_skip "requires root privileges"
1238c2ecf20Sopenharmony_ci	fi
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci# Look for config option in Kconfig file.
1278c2ecf20Sopenharmony_ci# Return 1 for found and 0 for not found.
1288c2ecf20Sopenharmony_cikconfig_enabled()
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	local config="$1"
1318c2ecf20Sopenharmony_ci	local msg="$2"
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	grep -E -q $config $IKCONFIG
1348c2ecf20Sopenharmony_ci	if [ $? -eq 0 ]; then
1358c2ecf20Sopenharmony_ci		log_info "$msg"
1368c2ecf20Sopenharmony_ci		return 1
1378c2ecf20Sopenharmony_ci	fi
1388c2ecf20Sopenharmony_ci	return 0
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci# Attempt to get the kernel config first via proc, and then by
1428c2ecf20Sopenharmony_ci# extracting it from the kernel image or the configs.ko using
1438c2ecf20Sopenharmony_ci# scripts/extract-ikconfig.
1448c2ecf20Sopenharmony_ci# Return 1 for found.
1458c2ecf20Sopenharmony_ciget_kconfig()
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	local proc_config="/proc/config.gz"
1488c2ecf20Sopenharmony_ci	local module_dir="/lib/modules/`uname -r`"
1498c2ecf20Sopenharmony_ci	local configs_module="$module_dir/kernel/kernel/configs.ko"
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if [ ! -f $proc_config ]; then
1528c2ecf20Sopenharmony_ci		modprobe configs > /dev/null 2>&1
1538c2ecf20Sopenharmony_ci	fi
1548c2ecf20Sopenharmony_ci	if [ -f $proc_config ]; then
1558c2ecf20Sopenharmony_ci		cat $proc_config | gunzip > $IKCONFIG 2>/dev/null
1568c2ecf20Sopenharmony_ci		if [ $? -eq 0 ]; then
1578c2ecf20Sopenharmony_ci			return 1
1588c2ecf20Sopenharmony_ci		fi
1598c2ecf20Sopenharmony_ci	fi
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	local extract_ikconfig="$module_dir/source/scripts/extract-ikconfig"
1628c2ecf20Sopenharmony_ci	if [ ! -f $extract_ikconfig ]; then
1638c2ecf20Sopenharmony_ci		log_skip "extract-ikconfig not found"
1648c2ecf20Sopenharmony_ci	fi
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	$extract_ikconfig $KERNEL_IMAGE > $IKCONFIG 2>/dev/null
1678c2ecf20Sopenharmony_ci	if [ $? -eq 1 ]; then
1688c2ecf20Sopenharmony_ci		if [ ! -f $configs_module ]; then
1698c2ecf20Sopenharmony_ci			log_skip "CONFIG_IKCONFIG not enabled"
1708c2ecf20Sopenharmony_ci		fi
1718c2ecf20Sopenharmony_ci		$extract_ikconfig $configs_module > $IKCONFIG
1728c2ecf20Sopenharmony_ci		if [ $? -eq 1 ]; then
1738c2ecf20Sopenharmony_ci			log_skip "CONFIG_IKCONFIG not enabled"
1748c2ecf20Sopenharmony_ci		fi
1758c2ecf20Sopenharmony_ci	fi
1768c2ecf20Sopenharmony_ci	return 1
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci# Make sure that securityfs is mounted
1808c2ecf20Sopenharmony_cimount_securityfs()
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	if [ -z $SECURITYFS ]; then
1838c2ecf20Sopenharmony_ci		SECURITYFS=/sys/kernel/security
1848c2ecf20Sopenharmony_ci		mount -t securityfs security $SECURITYFS
1858c2ecf20Sopenharmony_ci	fi
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	if [ ! -d "$SECURITYFS" ]; then
1888c2ecf20Sopenharmony_ci		log_fail "$SECURITYFS :securityfs is not mounted"
1898c2ecf20Sopenharmony_ci	fi
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci# The policy rule format is an "action" followed by key-value pairs.  This
1938c2ecf20Sopenharmony_ci# function supports up to two key-value pairs, in any order.
1948c2ecf20Sopenharmony_ci# For example: action func=<keyword> [appraise_type=<type>]
1958c2ecf20Sopenharmony_ci# Return 1 for found and 0 for not found.
1968c2ecf20Sopenharmony_cicheck_ima_policy()
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	local action="$1"
1998c2ecf20Sopenharmony_ci	local keypair1="$2"
2008c2ecf20Sopenharmony_ci	local keypair2="$3"
2018c2ecf20Sopenharmony_ci	local ret=0
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	mount_securityfs
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	local ima_policy=$SECURITYFS/ima/policy
2068c2ecf20Sopenharmony_ci	if [ ! -e $ima_policy ]; then
2078c2ecf20Sopenharmony_ci		log_fail "$ima_policy not found"
2088c2ecf20Sopenharmony_ci	fi
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if [ -n $keypair2 ]; then
2118c2ecf20Sopenharmony_ci		grep -e "^$action.*$keypair1" "$ima_policy" | \
2128c2ecf20Sopenharmony_ci			grep -q -e "$keypair2"
2138c2ecf20Sopenharmony_ci	else
2148c2ecf20Sopenharmony_ci		grep -q -e "^$action.*$keypair1" "$ima_policy"
2158c2ecf20Sopenharmony_ci	fi
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	# invert "grep -q" result, returning 1 for found.
2188c2ecf20Sopenharmony_ci	[ $? -eq 0 ] && ret=1
2198c2ecf20Sopenharmony_ci	return $ret
2208c2ecf20Sopenharmony_ci}
221