cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

elf.c (6280B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * tools/testing/selftests/kvm/lib/elf.c
      4 *
      5 * Copyright (C) 2018, Google LLC.
      6 */
      7
      8#include "test_util.h"
      9
     10#include <bits/endian.h>
     11#include <linux/elf.h>
     12
     13#include "kvm_util.h"
     14#include "kvm_util_internal.h"
     15
     16static void elfhdr_get(const char *filename, Elf64_Ehdr *hdrp)
     17{
     18	off_t offset_rv;
     19
     20	/* Open the ELF file. */
     21	int fd;
     22	fd = open(filename, O_RDONLY);
     23	TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
     24		"  filename: %s\n"
     25		"  rv: %i errno: %i", filename, fd, errno);
     26
     27	/* Read in and validate ELF Identification Record.
     28	 * The ELF Identification record is the first 16 (EI_NIDENT) bytes
     29	 * of the ELF header, which is at the beginning of the ELF file.
     30	 * For now it is only safe to read the first EI_NIDENT bytes.  Once
     31	 * read and validated, the value of e_ehsize can be used to determine
     32	 * the real size of the ELF header.
     33	 */
     34	unsigned char ident[EI_NIDENT];
     35	test_read(fd, ident, sizeof(ident));
     36	TEST_ASSERT((ident[EI_MAG0] == ELFMAG0) && (ident[EI_MAG1] == ELFMAG1)
     37		&& (ident[EI_MAG2] == ELFMAG2) && (ident[EI_MAG3] == ELFMAG3),
     38		"ELF MAGIC Mismatch,\n"
     39		"  filename: %s\n"
     40		"  ident[EI_MAG0 - EI_MAG3]: %02x %02x %02x %02x\n"
     41		"  Expected: %02x %02x %02x %02x",
     42		filename,
     43		ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3],
     44		ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3);
     45	TEST_ASSERT(ident[EI_CLASS] == ELFCLASS64,
     46		"Current implementation only able to handle ELFCLASS64,\n"
     47		"  filename: %s\n"
     48		"  ident[EI_CLASS]: %02x\n"
     49		"  expected: %02x",
     50		filename,
     51		ident[EI_CLASS], ELFCLASS64);
     52	TEST_ASSERT(((BYTE_ORDER == LITTLE_ENDIAN)
     53			&& (ident[EI_DATA] == ELFDATA2LSB))
     54		|| ((BYTE_ORDER == BIG_ENDIAN)
     55			&& (ident[EI_DATA] == ELFDATA2MSB)), "Current "
     56		"implementation only able to handle\n"
     57		"cases where the host and ELF file endianness\n"
     58		"is the same:\n"
     59		"  host BYTE_ORDER: %u\n"
     60		"  host LITTLE_ENDIAN: %u\n"
     61		"  host BIG_ENDIAN: %u\n"
     62		"  ident[EI_DATA]: %u\n"
     63		"  ELFDATA2LSB: %u\n"
     64		"  ELFDATA2MSB: %u",
     65		BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN,
     66		ident[EI_DATA], ELFDATA2LSB, ELFDATA2MSB);
     67	TEST_ASSERT(ident[EI_VERSION] == EV_CURRENT,
     68		"Current implementation only able to handle current "
     69		"ELF version,\n"
     70		"  filename: %s\n"
     71		"  ident[EI_VERSION]: %02x\n"
     72		"  expected: %02x",
     73		filename, ident[EI_VERSION], EV_CURRENT);
     74
     75	/* Read in the ELF header.
     76	 * With the ELF Identification portion of the ELF header
     77	 * validated, especially that the value at EI_VERSION is
     78	 * as expected, it is now safe to read the entire ELF header.
     79	 */
     80	offset_rv = lseek(fd, 0, SEEK_SET);
     81	TEST_ASSERT(offset_rv == 0, "Seek to ELF header failed,\n"
     82		"  rv: %zi expected: %i", offset_rv, 0);
     83	test_read(fd, hdrp, sizeof(*hdrp));
     84	TEST_ASSERT(hdrp->e_phentsize == sizeof(Elf64_Phdr),
     85		"Unexpected physical header size,\n"
     86		"  hdrp->e_phentsize: %x\n"
     87		"  expected: %zx",
     88		hdrp->e_phentsize, sizeof(Elf64_Phdr));
     89	TEST_ASSERT(hdrp->e_shentsize == sizeof(Elf64_Shdr),
     90		"Unexpected section header size,\n"
     91		"  hdrp->e_shentsize: %x\n"
     92		"  expected: %zx",
     93		hdrp->e_shentsize, sizeof(Elf64_Shdr));
     94}
     95
     96/* VM ELF Load
     97 *
     98 * Input Args:
     99 *   filename - Path to ELF file
    100 *
    101 * Output Args: None
    102 *
    103 * Input/Output Args:
    104 *   vm - Pointer to opaque type that describes the VM.
    105 *
    106 * Return: None, TEST_ASSERT failures for all error conditions
    107 *
    108 * Loads the program image of the ELF file specified by filename,
    109 * into the virtual address space of the VM pointed to by vm.  On entry
    110 * the VM needs to not be using any of the virtual address space used
    111 * by the image and it needs to have sufficient available physical pages, to
    112 * back the virtual pages used to load the image.
    113 */
    114void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename)
    115{
    116	off_t offset, offset_rv;
    117	Elf64_Ehdr hdr;
    118
    119	/* Open the ELF file. */
    120	int fd;
    121	fd = open(filename, O_RDONLY);
    122	TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
    123		"  filename: %s\n"
    124		"  rv: %i errno: %i", filename, fd, errno);
    125
    126	/* Read in the ELF header. */
    127	elfhdr_get(filename, &hdr);
    128
    129	/* For each program header.
    130	 * The following ELF header members specify the location
    131	 * and size of the program headers:
    132	 *
    133	 *   e_phoff - File offset to start of program headers
    134	 *   e_phentsize - Size of each program header
    135	 *   e_phnum - Number of program header entries
    136	 */
    137	for (unsigned int n1 = 0; n1 < hdr.e_phnum; n1++) {
    138		/* Seek to the beginning of the program header. */
    139		offset = hdr.e_phoff + (n1 * hdr.e_phentsize);
    140		offset_rv = lseek(fd, offset, SEEK_SET);
    141		TEST_ASSERT(offset_rv == offset,
    142			"Failed to seek to begining of program header %u,\n"
    143			"  filename: %s\n"
    144			"  rv: %jd errno: %i",
    145			n1, filename, (intmax_t) offset_rv, errno);
    146
    147		/* Read in the program header. */
    148		Elf64_Phdr phdr;
    149		test_read(fd, &phdr, sizeof(phdr));
    150
    151		/* Skip if this header doesn't describe a loadable segment. */
    152		if (phdr.p_type != PT_LOAD)
    153			continue;
    154
    155		/* Allocate memory for this segment within the VM. */
    156		TEST_ASSERT(phdr.p_memsz > 0, "Unexpected loadable segment "
    157			"memsize of 0,\n"
    158			"  phdr index: %u p_memsz: 0x%" PRIx64,
    159			n1, (uint64_t) phdr.p_memsz);
    160		vm_vaddr_t seg_vstart = align_down(phdr.p_vaddr, vm->page_size);
    161		vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1;
    162		seg_vend |= vm->page_size - 1;
    163		size_t seg_size = seg_vend - seg_vstart + 1;
    164
    165		vm_vaddr_t vaddr = vm_vaddr_alloc(vm, seg_size, seg_vstart);
    166		TEST_ASSERT(vaddr == seg_vstart, "Unable to allocate "
    167			"virtual memory for segment at requested min addr,\n"
    168			"  segment idx: %u\n"
    169			"  seg_vstart: 0x%lx\n"
    170			"  vaddr: 0x%lx",
    171			n1, seg_vstart, vaddr);
    172		memset(addr_gva2hva(vm, vaddr), 0, seg_size);
    173		/* TODO(lhuemill): Set permissions of each memory segment
    174		 * based on the least-significant 3 bits of phdr.p_flags.
    175		 */
    176
    177		/* Load portion of initial state that is contained within
    178		 * the ELF file.
    179		 */
    180		if (phdr.p_filesz) {
    181			offset_rv = lseek(fd, phdr.p_offset, SEEK_SET);
    182			TEST_ASSERT(offset_rv == phdr.p_offset,
    183				"Seek to program segment offset failed,\n"
    184				"  program header idx: %u errno: %i\n"
    185				"  offset_rv: 0x%jx\n"
    186				"  expected: 0x%jx\n",
    187				n1, errno, (intmax_t) offset_rv,
    188				(intmax_t) phdr.p_offset);
    189			test_read(fd, addr_gva2hva(vm, phdr.p_vaddr),
    190				phdr.p_filesz);
    191		}
    192	}
    193}