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.