Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
test_kexec_jump
@@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
# Makefile for kexec tests
ARCH ?= $(shell uname -m 2>/dev/null || echo not)
ARCH_PROCESSED := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
ifeq ($(ARCH_PROCESSED),$(filter $(ARCH_PROCESSED),x86 ppc64le))
TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh
TEST_FILES := kexec_common_lib.sh
include ../../../scripts/Makefile.arch
ifeq ($(IS_64_BIT)$(ARCH_PROCESSED),1x86)
TEST_PROGS += test_kexec_jump.sh
TEST_GEN_PROGS := test_kexec_jump
endif
include ../lib.mk
endif
@@ -0,0 +1,3 @@
CONFIG_IMA_APPRAISE=y
CONFIG_IMA_ARCH_POLICY=y
CONFIG_SECURITYFS=y
@@ -0,0 +1,219 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4
VERBOSE="${VERBOSE:-1}"
IKCONFIG="/tmp/config-`uname -r`"
KERNEL_IMAGE="/boot/vmlinuz-`uname -r`"
SECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}')
log_info()
{
[ $VERBOSE -ne 0 ] && echo "[INFO] $1"
}
# The ksefltest framework requirement returns 0 for PASS.
log_pass()
{
[ $VERBOSE -ne 0 ] && echo "$1 [PASS]"
exit 0
}
# The ksefltest framework requirement returns 1 for FAIL.
log_fail()
{
[ $VERBOSE -ne 0 ] && echo "$1 [FAIL]"
exit 1
}
# The ksefltest framework requirement returns 4 for SKIP.
log_skip()
{
[ $VERBOSE -ne 0 ] && echo "$1"
exit 4
}
# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
# (Based on kdump-lib.sh)
get_efivarfs_secureboot_mode()
{
local efivarfs="/sys/firmware/efi/efivars"
local secure_boot_file=""
local setup_mode_file=""
local secureboot_mode=0
local setup_mode=0
# Make sure that efivar_fs is mounted in the normal location
if ! grep -q "^\S\+ $efivarfs efivarfs" /proc/mounts; then
log_info "efivars is not mounted on $efivarfs"
return 0;
fi
secure_boot_file=$(find "$efivarfs" -name SecureBoot-* 2>/dev/null)
setup_mode_file=$(find "$efivarfs" -name SetupMode-* 2>/dev/null)
if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secureboot_mode=$(hexdump -v -e '/1 "%d\ "' \
"$secure_boot_file"|cut -d' ' -f 5)
setup_mode=$(hexdump -v -e '/1 "%d\ "' \
"$setup_mode_file"|cut -d' ' -f 5)
if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then
log_info "secure boot mode enabled (CONFIG_EFIVAR_FS)"
return 1;
fi
fi
return 0;
}
# On powerpc platform, check device-tree property
# /proc/device-tree/ibm,secureboot/os-secureboot-enforcing
# to detect secureboot state.
get_ppc64_secureboot_mode()
{
local secure_boot_file="/proc/device-tree/ibm,secureboot/os-secureboot-enforcing"
# Check for secure boot file existence
if [ -f $secure_boot_file ]; then
log_info "Secureboot is enabled (Device tree)"
return 1;
fi
log_info "Secureboot is not enabled (Device tree)"
return 0;
}
# Return the architecture of the system
get_arch()
{
echo $(arch)
}
# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID).
# The secure boot mode can be accessed as the last integer of
# "od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-*". The efi
# SetupMode can be similarly accessed.
# Return 1 for SecureBoot mode enabled and SetupMode mode disabled.
get_secureboot_mode()
{
local secureboot_mode=0
local system_arch=$(get_arch)
if [ "$system_arch" == "ppc64le" ]; then
get_ppc64_secureboot_mode
secureboot_mode=$?
else
get_efivarfs_secureboot_mode
secureboot_mode=$?
fi
if [ $secureboot_mode -eq 0 ]; then
log_info "secure boot mode not enabled"
fi
return $secureboot_mode;
}
require_root_privileges()
{
if [ $(id -ru) -ne 0 ]; then
log_skip "requires root privileges"
fi
}
# Look for config option in Kconfig file.
# Return 1 for found and 0 for not found.
kconfig_enabled()
{
local config="$1"
local msg="$2"
grep -E -q $config $IKCONFIG
if [ $? -eq 0 ]; then
log_info "$msg"
return 1
fi
return 0
}
# Attempt to get the kernel config first by checking the modules directory
# then via proc, and finally by extracting it from the kernel image or the
# configs.ko using scripts/extract-ikconfig.
# Return 1 for found.
get_kconfig()
{
local proc_config="/proc/config.gz"
local module_dir="/lib/modules/`uname -r`"
local configs_module="$module_dir/kernel/kernel/configs.ko*"
if [ -f $module_dir/config ]; then
IKCONFIG=$module_dir/config
return 1
fi
if [ ! -f $proc_config ]; then
modprobe configs > /dev/null 2>&1
fi
if [ -f $proc_config ]; then
cat $proc_config | gunzip > $IKCONFIG 2>/dev/null
if [ $? -eq 0 ]; then
return 1
fi
fi
local extract_ikconfig="$module_dir/source/scripts/extract-ikconfig"
if [ ! -f $extract_ikconfig ]; then
log_skip "extract-ikconfig not found"
fi
$extract_ikconfig $KERNEL_IMAGE > $IKCONFIG 2>/dev/null
if [ $? -eq 1 ]; then
if [ ! -f $configs_module ]; then
log_skip "CONFIG_IKCONFIG not enabled"
fi
$extract_ikconfig $configs_module > $IKCONFIG
if [ $? -eq 1 ]; then
log_skip "CONFIG_IKCONFIG not enabled"
fi
fi
return 1
}
# Make sure that securityfs is mounted
mount_securityfs()
{
if [ -z $SECURITYFS ]; then
SECURITYFS=/sys/kernel/security
mount -t securityfs security $SECURITYFS
fi
if [ ! -d "$SECURITYFS" ]; then
log_fail "$SECURITYFS :securityfs is not mounted"
fi
}
# The policy rule format is an "action" followed by key-value pairs. This
# function supports up to two key-value pairs, in any order.
# For example: action func=<keyword> [appraise_type=<type>]
# Return 1 for found and 0 for not found.
check_ima_policy()
{
local action="$1"
local keypair1="$2"
local keypair2="$3"
local ret=0
mount_securityfs
local ima_policy=$SECURITYFS/ima/policy
if [ ! -e $ima_policy ]; then
log_fail "$ima_policy not found"
fi
if [ -n $keypair2 ]; then
grep -e "^$action.*$keypair1" "$ima_policy" | \
grep -q -e "$keypair2"
else
grep -q -e "^$action.*$keypair1" "$ima_policy"
fi
# invert "grep -q" result, returning 1 for found.
[ $? -eq 0 ] && ret=1
return $ret
}
@@ -0,0 +1,243 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Loading a kernel image via the kexec_file_load syscall can verify either
# the IMA signature stored in the security.ima xattr or the PE signature,
# both signatures depending on the IMA policy, or none.
#
# To determine whether the kernel image is signed, this test depends
# on pesign and getfattr. This test also requires the kernel to be
# built with CONFIG_IKCONFIG enabled and either CONFIG_IKCONFIG_PROC
# enabled or access to the extract-ikconfig script.
TEST="KEXEC_FILE_LOAD"
. ./kexec_common_lib.sh
trap "{ rm -f $IKCONFIG ; }" EXIT
# Some of the IMA builtin policies may require the kexec kernel image to
# be signed, but these policy rules may be replaced with a custom
# policy. Only CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS persists after
# loading a custom policy. Check if it is enabled, before reading the
# IMA runtime sysfs policy file.
# Return 1 for IMA signature required and 0 for not required.
is_ima_sig_required()
{
local ret=0
kconfig_enabled "CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS=y" \
"IMA kernel image signature required"
if [ $? -eq 1 ]; then
log_info "IMA signature required"
return 1
fi
# The architecture specific or a custom policy may require the
# kexec kernel image be signed. Policy rules are walked
# sequentially. As a result, a policy rule may be defined, but
# might not necessarily be used. This test assumes if a policy
# rule is specified, that is the intent.
# First check for appended signature (modsig), then xattr
if [ $ima_read_policy -eq 1 ]; then
check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
"appraise_type=imasig|modsig"
ret=$?
if [ $ret -eq 1 ]; then
log_info "IMA or appended(modsig) signature required"
else
check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
"appraise_type=imasig"
ret=$?
[ $ret -eq 1 ] && log_info "IMA signature required";
fi
fi
return $ret
}
# The kexec_file_load_test() is complicated enough, require pesign.
# Return 1 for PE signature found and 0 for not found.
check_for_pesig()
{
which pesign > /dev/null 2>&1 || log_skip "pesign not found"
pesign -i $KERNEL_IMAGE --show-signature | grep -q "No signatures"
local ret=$?
if [ $ret -eq 1 ]; then
log_info "kexec kernel image PE signed"
else
log_info "kexec kernel image not PE signed"
fi
return $ret
}
# The kexec_file_load_test() is complicated enough, require getfattr.
# Return 1 for IMA signature found and 0 for not found.
check_for_imasig()
{
local ret=0
which getfattr > /dev/null 2>&1
if [ $? -eq 1 ]; then
log_skip "getfattr not found"
fi
line=$(getfattr -n security.ima -e hex --absolute-names $KERNEL_IMAGE 2>&1)
echo $line | grep -q "security.ima=0x03"
if [ $? -eq 0 ]; then
ret=1
log_info "kexec kernel image IMA signed"
else
log_info "kexec kernel image not IMA signed"
fi
return $ret
}
# Return 1 for appended signature (modsig) found and 0 for not found.
check_for_modsig()
{
local module_sig_string="~Module signature appended~"
local ret=0
tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE | \
grep -q "$module_sig_string"
if [ $? -eq 0 ]; then
ret=1
log_info "kexec kernel image modsig signed"
else
log_info "kexec kernel image not modsig signed"
fi
return $ret
}
kexec_file_load_test()
{
local succeed_msg="kexec_file_load succeeded"
local failed_msg="kexec_file_load failed"
local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING"
line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1)
if [ $? -eq 0 ]; then
kexec --unload --kexec-file-syscall
# In secureboot mode with an architecture specific
# policy, make sure either an IMA or PE signature exists.
if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \
[ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \
&& [ $ima_modsig -eq 0 ]; then
log_fail "$succeed_msg (missing sig)"
fi
if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
&& [ $pe_signed -eq 0 ]; then
log_fail "$succeed_msg (missing PE sig)"
fi
if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \
&& [ $ima_modsig -eq 0 ]; then
log_fail "$succeed_msg (missing IMA sig)"
fi
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
&& [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
&& [ $ima_read_policy -eq 0 ]; then
log_fail "$succeed_msg (possibly missing IMA sig)"
fi
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then
log_info "No signature verification required"
elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
&& [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
&& [ $ima_read_policy -eq 1 ]; then
log_info "No signature verification required"
fi
log_pass "$succeed_msg"
fi
# Check the reason for the kexec_file_load failure
echo $line | grep -q "Required key not available"
if [ $? -eq 0 ]; then
if [ $platform_keyring -eq 0 ]; then
log_pass "$failed_msg (-ENOKEY), $key_msg"
else
log_pass "$failed_msg (-ENOKEY)"
fi
fi
if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
&& [ $pe_signed -eq 0 ]; then
log_pass "$failed_msg (missing PE sig)"
fi
if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then
log_pass "$failed_msg (missing IMA sig)"
fi
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
&& [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \
&& [ $ima_signed -eq 0 ]; then
log_pass "$failed_msg (possibly missing IMA sig)"
fi
log_pass "$failed_msg"
return 0
}
# kexec requires root privileges
require_root_privileges
# get the kernel config
get_kconfig
kconfig_enabled "CONFIG_KEXEC_FILE=y" "kexec_file_load is enabled"
if [ $? -eq 0 ]; then
log_skip "kexec_file_load is not enabled"
fi
# Determine which kernel config options are enabled
kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
ima_appraise=$?
kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
"architecture specific policy enabled"
arch_policy=$?
kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \
"platform keyring enabled"
platform_keyring=$?
kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted"
ima_read_policy=$?
kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \
"kexec signed kernel image required"
kexec_sig_required=$?
kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \
"PE signed kernel image required"
pe_sig_required=$?
is_ima_sig_required
ima_sig_required=$?
get_secureboot_mode
secureboot=$?
# Are there pe and ima signatures
if [ "$(get_arch)" == 'ppc64le' ]; then
pe_signed=0
else
check_for_pesig
pe_signed=$?
fi
check_for_imasig
ima_signed=$?
check_for_modsig
ima_modsig=$?
# Test loading the kernel image via kexec_file_load syscall
kexec_file_load_test
@@ -0,0 +1,72 @@
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/kexec.h>
#include <linux/reboot.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
asm(
" .code64\n"
" .data\n"
"purgatory_start:\n"
// Trigger kexec debug exception handling
" int3\n"
// Set load address for next time
" leaq purgatory_start_b(%rip), %r11\n"
" movq %r11, 8(%rsp)\n"
// Back to Linux
" ret\n"
// Same again
"purgatory_start_b:\n"
// Trigger kexec debug exception handling
" int3\n"
// Set load address for next time
" leaq purgatory_start(%rip), %r11\n"
" movq %r11, 8(%rsp)\n"
// Back to Linux
" ret\n"
"purgatory_end:\n"
".previous"
);
extern char purgatory_start[], purgatory_end[];
int main (void)
{
struct kexec_segment segment = {};
int ret;
segment.buf = purgatory_start;
segment.bufsz = purgatory_end - purgatory_start;
segment.mem = (void *)0x400000;
segment.memsz = 0x1000;
ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT);
if (ret) {
perror("kexec_load");
exit(1);
}
ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
if (ret) {
perror("kexec reboot");
exit(1);
}
ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
if (ret) {
perror("kexec reboot");
exit(1);
}
printf("Success\n");
return 0;
}
@@ -0,0 +1,42 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Prevent loading a kernel image via the kexec_load syscall when
# signatures are required. (Dependent on CONFIG_IMA_ARCH_POLICY.)
TEST="$0"
. ./kexec_common_lib.sh
# kexec requires root privileges
require_root_privileges
# get the kernel config
get_kconfig
kconfig_enabled "CONFIG_KEXEC_JUMP=y" "kexec_jump is enabled"
if [ $? -eq 0 ]; then
log_skip "kexec_jump is not enabled"
fi
kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
ima_appraise=$?
kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
"IMA architecture specific policy enabled"
arch_policy=$?
get_secureboot_mode
secureboot=$?
if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ]; then
log_skip "Secure boot and CONFIG_IMA_ARCH_POLICY are enabled"
fi
./test_kexec_jump
if [ $? -eq 0 ]; then
log_pass "kexec_jump succeeded"
else
# The more likely failure mode if anything went wrong is that the
# kernel just crashes. But if we get back here, sure, whine anyway.
log_fail "kexec_jump failed"
fi
@@ -0,0 +1,47 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Prevent loading a kernel image via the kexec_load syscall when
# signatures are required. (Dependent on CONFIG_IMA_ARCH_POLICY.)
TEST="$0"
. ./kexec_common_lib.sh
# kexec requires root privileges
require_root_privileges
# get the kernel config
get_kconfig
kconfig_enabled "CONFIG_KEXEC=y" "kexec_load is enabled"
if [ $? -eq 0 ]; then
log_skip "kexec_load is not enabled"
fi
kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
ima_appraise=$?
kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
"IMA architecture specific policy enabled"
arch_policy=$?
get_secureboot_mode
secureboot=$?
# kexec_load should fail in secure boot mode and CONFIG_IMA_ARCH_POLICY enabled
kexec --load $KERNEL_IMAGE > /dev/null 2>&1
if [ $? -eq 0 ]; then
kexec --unload
if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ]; then
log_fail "kexec_load succeeded"
elif [ $ima_appraise -eq 0 -o $arch_policy -eq 0 ]; then
log_info "Either IMA or the IMA arch policy is not enabled"
fi
log_pass "kexec_load succeeded"
else
if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] ; then
log_pass "kexec_load failed"
else
log_fail "kexec_load failed"
fi
fi