[PATCH 14/14] arm64: kexec_file: add vmlinux format support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Aug 24, 2017 at 05:18:11PM +0900, AKASHI Takahiro wrote:
> The first PT_LOAD segment, which is assumed to be "text" code, in vmlinux
> will be loaded at the offset of TEXT_OFFSET from the begining of system
> memory. The other PT_LOAD segments are placed relative to the first one.

I really don't like assuming things about the vmlinux ELF file.

> Regarding kernel verification, since there is no standard way to contain
> a signature within elf binary, we follow PowerPC's (not yet upstreamed)
> approach, that is, appending a signature right after the kernel binary
> itself like module signing.

I also *really* don't like this. It's a bizarre in-band mechanism,
without explcit information. It's not a nice ABI.

If we can load an Image, why do we need to be able to load a vmlinux?

[...]

> diff --git a/arch/arm64/kernel/kexec_elf.c b/arch/arm64/kernel/kexec_elf.c
> new file mode 100644
> index 000000000000..7bd3c1e1f65a
> --- /dev/null
> +++ b/arch/arm64/kernel/kexec_elf.c
> @@ -0,0 +1,216 @@
> +/*
> + * Kexec vmlinux loader
> +
> + * Copyright (C) 2017 Linaro Limited
> + * Authors: AKASHI Takahiro <takahiro.akashi at linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#define pr_fmt(fmt)	"kexec_file(elf): " fmt
> +
> +#include <linux/elf.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/kexec.h>
> +#include <linux/module_signature.h>
> +#include <linux/types.h>
> +#include <linux/verification.h>
> +#include <asm/byteorder.h>
> +#include <asm/kexec_file.h>
> +#include <asm/memory.h>
> +
> +static int elf64_probe(const char *buf, unsigned long len)
> +{
> +	struct elfhdr ehdr;
> +
> +	/* Check for magic and architecture */
> +	memcpy(&ehdr, buf, sizeof(ehdr));
> +	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) ||
> +		(elf16_to_cpu(&ehdr, ehdr.e_machine) != EM_AARCH64))
> +		return -ENOEXEC;
> +
> +	return 0;
> +}
> +
> +static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
> +			 struct elf_info *elf_info,
> +			 unsigned long *kernel_load_addr)
> +{
> +	struct kexec_buf kbuf;
> +	const struct elf_phdr *phdr;
> +	const struct arm64_image_header *h;
> +	unsigned long text_offset, rand_offset;
> +	unsigned long page_offset, phys_offset;
> +	int first_segment, i, ret = -ENOEXEC;
> +
> +	kbuf.image = image;
> +	if (image->type == KEXEC_TYPE_CRASH) {
> +		kbuf.buf_min = crashk_res.start;
> +		kbuf.buf_max = crashk_res.end + 1;
> +	} else {
> +		kbuf.buf_min = 0;
> +		kbuf.buf_max = ULONG_MAX;
> +	}
> +	kbuf.top_down = 0;
> +
> +	/* Load PT_LOAD segments. */
> +	for (i = 0, first_segment = 1; i < ehdr->e_phnum; i++) {
> +		phdr = &elf_info->proghdrs[i];
> +		if (phdr->p_type != PT_LOAD)
> +			continue;
> +
> +		kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
> +		kbuf.bufsz = min(phdr->p_filesz, phdr->p_memsz);
> +		kbuf.memsz = phdr->p_memsz;
> +		kbuf.buf_align = phdr->p_align;
> +
> +		if (first_segment) {
> +			/*
> +			 * Identify TEXT_OFFSET:
> +			 * When CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET=y the image
> +			 * header could be offset in the elf segment. The linker
> +			 * script sets ehdr->e_entry to the start of text.

Please, let's not have to go delving into the vmlinux, knowing intimate
details about how it's put together.

> +			 *
> +			 * NOTE: In v3.16 or older, h->text_offset is 0,
> +			 * so use the default, 0x80000
> +			 */
> +			rand_offset = ehdr->e_entry - phdr->p_vaddr;
> +			h = (struct arm64_image_header *)
> +					(elf_info->buffer + phdr->p_offset +
> +					rand_offset);
> +
> +			if (!arm64_header_check_magic(h))
> +				goto out;
> +
> +			if (h->image_size)
> +				text_offset = le64_to_cpu(h->text_offset);
> +			else
> +				text_offset = 0x80000;

Surely we can share the Image header parsing with the Image parser?

The Image code had practically the exact same logic operating on the
header struct.

Thanks,
Mark.



[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux