[PATCH v10 00/14] arm64: kexec: add kexec_file_load() support
From: AKASHI Takahiro
Date: Fri Jun 22 2018 - 22:20:48 EST
This is the tenth round of implementing kexec_file_load() support
on arm64.[1] (See "Changes" below)
Most of the code is based on kexec-tools.
This patch series enables us to
* load the kernel by specifying its file descriptor, instead of user-
filled buffer, at kexec_file_load() system call, and
* optionally verify its signature at load time for trusted boot.
Kernel virtual address randomization is also supported since v9.
Contrary to kexec_load() system call, as we discussed a long time ago,
users may not be allowed to provide a device tree to the 2nd kernel
explicitly, hence enforcing a dt blob of the first kernel to be re-used
internally.
To use kexec_file_load() system call, instead of kexec_load(), at kexec
command, '-s' option must be specified. See [2] for a necessary patch for
kexec-tools.
To analyze a generated crash dump file, use the latest master branch of
crash utility[3]. I always try to submit patches to fix any inconsistencies
introduced in the latest kernel.
Regarding a kernel image verification, a signature must be presented
along with the binary itself. A signature is basically a hash value
calculated against the whole binary data and encrypted by a key which
will be authenticated by one of the system's trusted certificates.
Any attempt to read and load a to-be-kexec-ed kernel image through
a system call will be checked and blocked if the binary's hash value
doesn't match its associated signature.
There are two methods available now:
1. implementing arch-specific verification hook of kexec_file_load()
2. utilizing IMA(Integrity Measurement Architecture)[4] appraisal framework
Before my v7, I believed that my patch only supports (1) but am now
confident that (2) comes free if IMA is enabled and properly configured.
(1) Arch-specific verification hook
If CONFIG_KEXEC_VERIFY_SIG is enabled, kexec_file_load() invokes an arch-
defined (and hence file-format-specific) hook function to check for the
validity of kernel binary.
On x86, a signature is embedded into a PE file (Microsoft's format) header
of binary. Since arm64's "Image" can also be seen as a PE file as far as
CONFIG_EFI is enabled, we adopt this format for kernel signing.
As in the case of UEFI applications, we can create a signed kernel image:
$ sbsign --key ${KEY} --cert ${CERT} Image
You may want to use certs/signing_key.pem, which is intended to be used
for module signing (CONFIG_MODULE_SIG), as ${KEY} and ${CERT} for test
purpose.
(2) IMA appraisal-based
IMA was first introduced in linux in order to meet TCG (Trusted Computing
Group) requirement that all the sensitive files be *measured* before
reading/executing them to detect any untrusted changes/modification.
Then appraisal feature, which allows us to ensure the integrity of
files and even prevent them from reading/executing, was added later.
Meanwhile, kexec_file_load() has been merged since v3.17 and evolved to
enable IMA-appraisal type verification by the commit b804defe4297 ("kexec:
replace call to copy_file_from_fd() with kernel version").
In this scheme, a signature will be stored in a extended file attribute,
"security.ima" while a decryption key is hold in a dedicated keyring,
".ima" or "_ima". All the necessary process of verification is confined
in a secure API, kernel_read_file_from_fd(), called by kexec_file_load().
Please note that powerpc is one of the two architectures now
supporting KEXEC_FILE, and that it wishes to exntend IMA,
where a signature may be appended to "vmlinux" file[5], like module
signing, instead of using an extended file attribute.
While IMA meant to be used with TPM (Trusted Platform Module) on secure
platform, IMA is still usable without TPM. Here is an example procedure
about how we can give it a try to run the feature using a self-signed
root ca for demo/test purposes:
1) Generate needed keys and certificates, following "Generate trusted
keys" section in README of ima-evm-utils[6].
2) Build the kernel with the following kernel configurations, specifying
"ima-local-ca.pem" for CONFIG_SYSTEM_TRUSTED_KEYS:
CONFIG_EXT4_FS_SECURITY
CONFIG_INTEGRITY_SIGNATURE
CONFIG_INTEGRITY_ASYMMETRIC_KEYS
CONFIG_INTEGRITY_TRUSTED_KEYRING
CONFIG_IMA
CONFIG_IMA_WRITE_POLICY
CONFIG_IMA_READ_POLICY
CONFIG_IMA_APPRAISE
CONFIG_IMA_APPRAISE_BOOTPARAM
CONFIG_SYSTEM_TRUSTED_KEYS
Please note that CONFIG_KEXEC_VERIFY_SIG is not, actually should
not be, enabled.
3) Sign(label) a kernel image binary to be kexec-ed on target filesystem:
$ evmctl ima_sign --key /path/to/private_key.pem /your/Image
4) Add a command line parameter and boot the kernel:
ima_appraise=enforce
On live system,
5) Set a security policy:
$ mount -t securityfs none /sys/kernel/security
$ echo "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig" \
> /sys/kernel/security/ima/policy
6) Add a key for ima:
$ keyctl padd asymmetric my_ima_key %:.ima < /path/to/x509_ima.der
(or evmctl import /path/to/x509_ima.der <ima_keyring_id>)
7) Then try kexec as normal.
Concerns(or future works):
* Support for physical address randomization
* Signature verification of big endian kernel with CONFIG_KEXEC_VERIFY_SIG
While big-endian kernel can support kernel signing, I'm not sure that
Image can be recognized as in PE format because x86 standard only
defines little-endian-based format.
* Support for vminux loading
[1] http://git.linaro.org/people/takahiro.akashi/linux-aarch64.git
branch:arm64/kexec_file
[2] http://git.linaro.org/people/takahiro.akashi/kexec-tools.git
branch:arm64/kexec_file
[3] http://github.com/crash-utility/crash.git
[4] https://sourceforge.net/p/linux-ima/wiki/Home/
[5] http://lkml.iu.edu//hypermail/linux/kernel/1707.0/03669.html
[6] https://sourceforge.net/p/linux-ima/ima-evm-utils/ci/master/tree/
Changes in v10 (June 23, 2018)
* rebased to v4.18-rc
* change syscall numer of kexec_file_load from 292 to 293
* factor out memblock-based arch_kexec_walk_mem() from powerpc and
merge it into generic one
* move generic fdt helper functions from arm64 dir to drivers/of
(dt_root_[addr|size]_cells are no longer __initdata.)
* modify fill_property() to use 'while' loop
* modify fdt_setprop_reg() to allocate a buffer on stack
* modify setup_dtb() to use fdt_setprop_u64()
* pass kernel_load_addr/size directly as arguments, instead of via
kimage_arch.kern_segment, at load_other_segments()
* refuse loading an image which cannot be supported in image loader,
adding cpu-feature(MMFR0) helper functions
* modify prepare_elf_headers() to use kmalloc() instead of vmalloc()
* always pass arch.dtb_mem as the fourth argument to cpu_soft_restart()
in machine_kexec() while dtb_mem will be zero in kexec case
Changes in v9 (April 25, 2018)
* rebased to v4.17-rc
* remove preparatory patches on generic/x86/ppc code
They have now been merged in v4.17-rc1.
* allocate memory based on memblock list instead of system resources
This will prevent reserved regions, particularly UEFI/ACPI data,
from being corrupted.
* correct dt property names, linux,initrd-*, in newly-created dtb
"linux," was missing.
* remove alignment requirement for initrd loading
* add kaslr (kernel virtual address randomization) support
* misc code clean-up
* revise commit messages
Changes in v8 (Feb 22, 2018)
* introduce ARCH_HAS_KEXEC_PURGATORY so that arm64 will be able to skip
purgatory
* remove "ifdef CONFIG_X86_64" stuffs from a re-factored function,
prepare_elf64_headers(), making its interface more generic
(The original patch was split into two for easier reviews.)
* modify cpu_soft_restart() so as to let the 2nd kernel jump into its entry
code directly without requiring purgatory in case of kexec_file_load
* remove CONFIG_KEXEC_FILE_IMAGE_FMT and introduce
CONFIG_KEXEC_IMAGE_VERIFY_SIG, much similar to x86 but quite redundant
for now.
* In addition, update/modify dependencies of KEXEC_IMAGE_VERIFY_SIG
Changes in v7 (Dec 4, 2017)
* rebased to v4.15-rc2
* re-organize the patch set to separate KEXEC_FILE_VERIFY_SIG-related
code from the others
* revamp factored-out code in kernel/kexec_file.c due to the changes
in original x86 code
* redefine walk_sys_ram_res_rev() prototype due to change of callback
type in the counterpart, walk_sys_ram_res()
* make KEXEC_FILE_IMAGE_FMT default on if KEXEC_FILE selected
Changes in v6 (Oct 24, 2017)
* fix a for-loop bug in _kexec_kernel_image_probe() per Julien
Changes in v5 (Oct 10, 2017)
* fix kbuild errors around patch #3
per Julien's comments,
* fix a bug in walk_system_ram_res_rev() with some cleanup
* modify fdt_setprop_range() to use vmalloc()
* modify fill_property() to use memset()
Changes in v4 (Oct 2, 2017)
* reinstate x86's arch_kexec_kernel_image_load()
* rename weak arch_kexec_kernel_xxx() to _kexec_kernel_xxx() for
better re-use
* constify kexec_file_loaders[]
Changes in v3 (Sep 15, 2017)
* fix kbuild test error
* factor out arch_kexec_kernel_*() & arch_kimage_file_post_load_cleanup()
* remove CONFIG_CRASH_CORE guard from kexec_file.c
* add vmapped kernel region to vmcore for gdb backtracing
(see prepare_elf64_headers())
* merge asm/kexec_file.h into asm/kexec.h
* and some cleanups
Changes in v2 (Sep 8, 2017)
* move core-header-related functions from crash_core.c to kexec_file.c
* drop hash-check code from purgatory
* modify purgatory asm to remove arch_kexec_apply_relocations_add()
* drop older kernel support
* drop vmlinux support (at least, for this series)
Patch #1 to #10 are essential part for KEXEC_FILE support
(additionally allowing for IMA-based verification):
Patch #1 to #6 are all preparatory patches on generic side.
Patch #7 to #11 are to enable kexec_file_load on arm64.
Patch #12 to #13 are for KEXEC_VERIFY_SIG (arch-specific verification)
support
AKASHI Takahiro (14):
asm-generic: add kexec_file_load system call to unistd.h
kexec_file: make kexec_image_post_load_cleanup_default() global
powerpc, kexec_file: factor out memblock-based arch_kexec_walk_mem()
of/fdt: add helper functions for handling properties
arm64: add image head flag definitions
arm64: cpufeature: add MMFR0 helper functions
arm64: enable KEXEC_FILE config
arm64: kexec_file: load initrd and device-tree
arm64: kexec_file: allow for loading Image-format kernel
arm64: kexec_file: add crash dump support
arm64: kexec_file: invoke the kernel without purgatory
include: pe.h: remove message[] from mz header definition
arm64: kexec_file: add kernel signature verification support
arm64: kexec_file: add kaslr support
arch/arm64/Kconfig | 34 +++
arch/arm64/include/asm/boot.h | 15 +
arch/arm64/include/asm/cpufeature.h | 48 ++++
arch/arm64/include/asm/kexec.h | 48 ++++
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/cpu-reset.S | 8 +-
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/kexec_image.c | 128 +++++++++
arch/arm64/kernel/machine_kexec.c | 12 +-
arch/arm64/kernel/machine_kexec_file.c | 291 ++++++++++++++++++++
arch/arm64/kernel/relocate_kernel.S | 3 +-
arch/powerpc/kernel/machine_kexec_file_64.c | 53 ----
drivers/of/fdt.c | 62 ++++-
include/linux/kexec.h | 1 +
include/linux/of_fdt.h | 10 +-
include/linux/pe.h | 2 +-
include/uapi/asm-generic/unistd.h | 4 +-
kernel/kexec_file.c | 54 +++-
18 files changed, 709 insertions(+), 69 deletions(-)
create mode 100644 arch/arm64/kernel/kexec_image.c
create mode 100644 arch/arm64/kernel/machine_kexec_file.c
--
2.17.0