162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4
562306a36Sopenharmony_ci
662306a36Sopenharmony_ciVERBOSE="${VERBOSE:-1}"
762306a36Sopenharmony_ciIKCONFIG="/tmp/config-`uname -r`"
862306a36Sopenharmony_ciKERNEL_IMAGE="/boot/vmlinuz-`uname -r`"
962306a36Sopenharmony_ciSECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}')
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cilog_info()
1262306a36Sopenharmony_ci{
1362306a36Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "[INFO] $1"
1462306a36Sopenharmony_ci}
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci# The ksefltest framework requirement returns 0 for PASS.
1762306a36Sopenharmony_cilog_pass()
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1 [PASS]"
2062306a36Sopenharmony_ci	exit 0
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci# The ksefltest framework requirement returns 1 for FAIL.
2462306a36Sopenharmony_cilog_fail()
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1 [FAIL]"
2762306a36Sopenharmony_ci	exit 1
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci# The ksefltest framework requirement returns 4 for SKIP.
3162306a36Sopenharmony_cilog_skip()
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	[ $VERBOSE -ne 0 ] && echo "$1"
3462306a36Sopenharmony_ci	exit 4
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
3862306a36Sopenharmony_ci# (Based on kdump-lib.sh)
3962306a36Sopenharmony_ciget_efivarfs_secureboot_mode()
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	local efivarfs="/sys/firmware/efi/efivars"
4262306a36Sopenharmony_ci	local secure_boot_file=""
4362306a36Sopenharmony_ci	local setup_mode_file=""
4462306a36Sopenharmony_ci	local secureboot_mode=0
4562306a36Sopenharmony_ci	local setup_mode=0
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	# Make sure that efivar_fs is mounted in the normal location
4862306a36Sopenharmony_ci	if ! grep -q "^\S\+ $efivarfs efivarfs" /proc/mounts; then
4962306a36Sopenharmony_ci		log_info "efivars is not mounted on $efivarfs"
5062306a36Sopenharmony_ci		return 0;
5162306a36Sopenharmony_ci	fi
5262306a36Sopenharmony_ci	secure_boot_file=$(find "$efivarfs" -name SecureBoot-* 2>/dev/null)
5362306a36Sopenharmony_ci	setup_mode_file=$(find "$efivarfs" -name SetupMode-* 2>/dev/null)
5462306a36Sopenharmony_ci	if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
5562306a36Sopenharmony_ci		secureboot_mode=$(hexdump -v -e '/1 "%d\ "' \
5662306a36Sopenharmony_ci			"$secure_boot_file"|cut -d' ' -f 5)
5762306a36Sopenharmony_ci		setup_mode=$(hexdump -v -e '/1 "%d\ "' \
5862306a36Sopenharmony_ci			"$setup_mode_file"|cut -d' ' -f 5)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci		if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then
6162306a36Sopenharmony_ci			log_info "secure boot mode enabled (CONFIG_EFIVAR_FS)"
6262306a36Sopenharmony_ci			return 1;
6362306a36Sopenharmony_ci		fi
6462306a36Sopenharmony_ci	fi
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci# On powerpc platform, check device-tree property
6962306a36Sopenharmony_ci# /proc/device-tree/ibm,secureboot/os-secureboot-enforcing
7062306a36Sopenharmony_ci# to detect secureboot state.
7162306a36Sopenharmony_ciget_ppc64_secureboot_mode()
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	local secure_boot_file="/proc/device-tree/ibm,secureboot/os-secureboot-enforcing"
7462306a36Sopenharmony_ci	# Check for secure boot file existence
7562306a36Sopenharmony_ci	if [ -f $secure_boot_file ]; then
7662306a36Sopenharmony_ci		log_info "Secureboot is enabled (Device tree)"
7762306a36Sopenharmony_ci		return 1;
7862306a36Sopenharmony_ci	fi
7962306a36Sopenharmony_ci	log_info "Secureboot is not enabled (Device tree)"
8062306a36Sopenharmony_ci	return 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci# Return the architecture of the system
8462306a36Sopenharmony_ciget_arch()
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	echo $(arch)
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
9062306a36Sopenharmony_ci# The secure boot mode can be accessed as the last integer of
9162306a36Sopenharmony_ci# "od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-*".  The efi
9262306a36Sopenharmony_ci# SetupMode can be similarly accessed.
9362306a36Sopenharmony_ci# Return 1 for SecureBoot mode enabled and SetupMode mode disabled.
9462306a36Sopenharmony_ciget_secureboot_mode()
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	local secureboot_mode=0
9762306a36Sopenharmony_ci	local system_arch=$(get_arch)
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	if [ "$system_arch" == "ppc64le" ]; then
10062306a36Sopenharmony_ci		get_ppc64_secureboot_mode
10162306a36Sopenharmony_ci		secureboot_mode=$?
10262306a36Sopenharmony_ci	else
10362306a36Sopenharmony_ci		get_efivarfs_secureboot_mode
10462306a36Sopenharmony_ci		secureboot_mode=$?
10562306a36Sopenharmony_ci	fi
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if [ $secureboot_mode -eq 0 ]; then
10862306a36Sopenharmony_ci		log_info "secure boot mode not enabled"
10962306a36Sopenharmony_ci	fi
11062306a36Sopenharmony_ci	return $secureboot_mode;
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cirequire_root_privileges()
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	if [ $(id -ru) -ne 0 ]; then
11662306a36Sopenharmony_ci		log_skip "requires root privileges"
11762306a36Sopenharmony_ci	fi
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci# Look for config option in Kconfig file.
12162306a36Sopenharmony_ci# Return 1 for found and 0 for not found.
12262306a36Sopenharmony_cikconfig_enabled()
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	local config="$1"
12562306a36Sopenharmony_ci	local msg="$2"
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	grep -E -q $config $IKCONFIG
12862306a36Sopenharmony_ci	if [ $? -eq 0 ]; then
12962306a36Sopenharmony_ci		log_info "$msg"
13062306a36Sopenharmony_ci		return 1
13162306a36Sopenharmony_ci	fi
13262306a36Sopenharmony_ci	return 0
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci# Attempt to get the kernel config first by checking the modules directory
13662306a36Sopenharmony_ci# then via proc, and finally by extracting it from the kernel image or the
13762306a36Sopenharmony_ci# configs.ko using scripts/extract-ikconfig.
13862306a36Sopenharmony_ci# Return 1 for found.
13962306a36Sopenharmony_ciget_kconfig()
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	local proc_config="/proc/config.gz"
14262306a36Sopenharmony_ci	local module_dir="/lib/modules/`uname -r`"
14362306a36Sopenharmony_ci	local configs_module="$module_dir/kernel/kernel/configs.ko*"
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if [ -f $module_dir/config ]; then
14662306a36Sopenharmony_ci		IKCONFIG=$module_dir/config
14762306a36Sopenharmony_ci		return 1
14862306a36Sopenharmony_ci	fi
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if [ ! -f $proc_config ]; then
15162306a36Sopenharmony_ci		modprobe configs > /dev/null 2>&1
15262306a36Sopenharmony_ci	fi
15362306a36Sopenharmony_ci	if [ -f $proc_config ]; then
15462306a36Sopenharmony_ci		cat $proc_config | gunzip > $IKCONFIG 2>/dev/null
15562306a36Sopenharmony_ci		if [ $? -eq 0 ]; then
15662306a36Sopenharmony_ci			return 1
15762306a36Sopenharmony_ci		fi
15862306a36Sopenharmony_ci	fi
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	local extract_ikconfig="$module_dir/source/scripts/extract-ikconfig"
16162306a36Sopenharmony_ci	if [ ! -f $extract_ikconfig ]; then
16262306a36Sopenharmony_ci		log_skip "extract-ikconfig not found"
16362306a36Sopenharmony_ci	fi
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	$extract_ikconfig $KERNEL_IMAGE > $IKCONFIG 2>/dev/null
16662306a36Sopenharmony_ci	if [ $? -eq 1 ]; then
16762306a36Sopenharmony_ci		if [ ! -f $configs_module ]; then
16862306a36Sopenharmony_ci			log_skip "CONFIG_IKCONFIG not enabled"
16962306a36Sopenharmony_ci		fi
17062306a36Sopenharmony_ci		$extract_ikconfig $configs_module > $IKCONFIG
17162306a36Sopenharmony_ci		if [ $? -eq 1 ]; then
17262306a36Sopenharmony_ci			log_skip "CONFIG_IKCONFIG not enabled"
17362306a36Sopenharmony_ci		fi
17462306a36Sopenharmony_ci	fi
17562306a36Sopenharmony_ci	return 1
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci# Make sure that securityfs is mounted
17962306a36Sopenharmony_cimount_securityfs()
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	if [ -z $SECURITYFS ]; then
18262306a36Sopenharmony_ci		SECURITYFS=/sys/kernel/security
18362306a36Sopenharmony_ci		mount -t securityfs security $SECURITYFS
18462306a36Sopenharmony_ci	fi
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	if [ ! -d "$SECURITYFS" ]; then
18762306a36Sopenharmony_ci		log_fail "$SECURITYFS :securityfs is not mounted"
18862306a36Sopenharmony_ci	fi
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci# The policy rule format is an "action" followed by key-value pairs.  This
19262306a36Sopenharmony_ci# function supports up to two key-value pairs, in any order.
19362306a36Sopenharmony_ci# For example: action func=<keyword> [appraise_type=<type>]
19462306a36Sopenharmony_ci# Return 1 for found and 0 for not found.
19562306a36Sopenharmony_cicheck_ima_policy()
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	local action="$1"
19862306a36Sopenharmony_ci	local keypair1="$2"
19962306a36Sopenharmony_ci	local keypair2="$3"
20062306a36Sopenharmony_ci	local ret=0
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	mount_securityfs
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	local ima_policy=$SECURITYFS/ima/policy
20562306a36Sopenharmony_ci	if [ ! -e $ima_policy ]; then
20662306a36Sopenharmony_ci		log_fail "$ima_policy not found"
20762306a36Sopenharmony_ci	fi
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if [ -n $keypair2 ]; then
21062306a36Sopenharmony_ci		grep -e "^$action.*$keypair1" "$ima_policy" | \
21162306a36Sopenharmony_ci			grep -q -e "$keypair2"
21262306a36Sopenharmony_ci	else
21362306a36Sopenharmony_ci		grep -q -e "^$action.*$keypair1" "$ima_policy"
21462306a36Sopenharmony_ci	fi
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	# invert "grep -q" result, returning 1 for found.
21762306a36Sopenharmony_ci	[ $? -eq 0 ] && ret=1
21862306a36Sopenharmony_ci	return $ret
21962306a36Sopenharmony_ci}
220