[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20170824173049.GG29665@leverpostej>
Date: Thu, 24 Aug 2017 18:30:50 +0100
From: Mark Rutland <mark.rutland@....com>
To: AKASHI Takahiro <takahiro.akashi@...aro.org>
Cc: catalin.marinas@....com, will.deacon@....com,
bauerman@...ux.vnet.ibm.com, dhowells@...hat.com,
vgoyal@...hat.com, herbert@...dor.apana.org.au,
davem@...emloft.net, akpm@...ux-foundation.org, mpe@...erman.id.au,
dyoung@...hat.com, bhe@...hat.com, arnd@...db.de,
ard.biesheuvel@...aro.org, kexec@...ts.infradead.org,
linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Subject: Re: [PATCH 14/14] arm64: kexec_file: add vmlinux format support
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@...aro.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.
Powered by blists - more mailing lists