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

genvdso.c (7876B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2015 Imagination Technologies
      4 * Author: Alex Smith <alex.smith@imgtec.com>
      5 */
      6
      7/*
      8 * This tool is used to generate the real VDSO images from the raw image. It
      9 * first patches up the MIPS ABI flags and GNU attributes sections defined in
     10 * elf.S to have the correct name and type. It then generates a C source file
     11 * to be compiled into the kernel containing the VDSO image data and a
     12 * mips_vdso_image struct for it, including symbol offsets extracted from the
     13 * image.
     14 *
     15 * We need to be passed both a stripped and unstripped VDSO image. The stripped
     16 * image is compiled into the kernel, but we must also patch up the unstripped
     17 * image's ABI flags sections so that it can be installed and used for
     18 * debugging.
     19 */
     20
     21#include <sys/mman.h>
     22#include <sys/stat.h>
     23#include <sys/types.h>
     24
     25#include <byteswap.h>
     26#include <elf.h>
     27#include <errno.h>
     28#include <fcntl.h>
     29#include <inttypes.h>
     30#include <stdarg.h>
     31#include <stdbool.h>
     32#include <stdio.h>
     33#include <stdlib.h>
     34#include <string.h>
     35#include <unistd.h>
     36
     37/* Define these in case the system elf.h is not new enough to have them. */
     38#ifndef SHT_GNU_ATTRIBUTES
     39# define SHT_GNU_ATTRIBUTES	0x6ffffff5
     40#endif
     41#ifndef SHT_MIPS_ABIFLAGS
     42# define SHT_MIPS_ABIFLAGS	0x7000002a
     43#endif
     44
     45enum {
     46	ABI_O32 = (1 << 0),
     47	ABI_N32 = (1 << 1),
     48	ABI_N64 = (1 << 2),
     49
     50	ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64,
     51};
     52
     53/* Symbols the kernel requires offsets for. */
     54static struct {
     55	const char *name;
     56	const char *offset_name;
     57	unsigned int abis;
     58} vdso_symbols[] = {
     59	{ "__vdso_sigreturn", "off_sigreturn", ABI_O32 },
     60	{ "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL },
     61	{}
     62};
     63
     64static const char *program_name;
     65static const char *vdso_name;
     66static unsigned char elf_class;
     67static unsigned int elf_abi;
     68static bool need_swap;
     69static FILE *out_file;
     70
     71#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     72# define HOST_ORDER		ELFDATA2LSB
     73#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
     74# define HOST_ORDER		ELFDATA2MSB
     75#endif
     76
     77#define BUILD_SWAP(bits)						\
     78	static uint##bits##_t swap_uint##bits(uint##bits##_t val)	\
     79	{								\
     80		return need_swap ? bswap_##bits(val) : val;		\
     81	}
     82
     83BUILD_SWAP(16)
     84BUILD_SWAP(32)
     85BUILD_SWAP(64)
     86
     87#define __FUNC(name, bits) name##bits
     88#define _FUNC(name, bits) __FUNC(name, bits)
     89#define FUNC(name) _FUNC(name, ELF_BITS)
     90
     91#define __ELF(x, bits) Elf##bits##_##x
     92#define _ELF(x, bits) __ELF(x, bits)
     93#define ELF(x) _ELF(x, ELF_BITS)
     94
     95/*
     96 * Include genvdso.h twice with ELF_BITS defined differently to get functions
     97 * for both ELF32 and ELF64.
     98 */
     99
    100#define ELF_BITS 64
    101#include "genvdso.h"
    102#undef ELF_BITS
    103
    104#define ELF_BITS 32
    105#include "genvdso.h"
    106#undef ELF_BITS
    107
    108static void *map_vdso(const char *path, size_t *_size)
    109{
    110	int fd;
    111	struct stat stat;
    112	void *addr;
    113	const Elf32_Ehdr *ehdr;
    114
    115	fd = open(path, O_RDWR);
    116	if (fd < 0) {
    117		fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
    118			path, strerror(errno));
    119		return NULL;
    120	}
    121
    122	if (fstat(fd, &stat) != 0) {
    123		fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name,
    124			path, strerror(errno));
    125		close(fd);
    126		return NULL;
    127	}
    128
    129	addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
    130		    0);
    131	if (addr == MAP_FAILED) {
    132		fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name,
    133			path, strerror(errno));
    134		close(fd);
    135		return NULL;
    136	}
    137
    138	/* ELF32/64 header formats are the same for the bits we're checking. */
    139	ehdr = addr;
    140
    141	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
    142		fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name,
    143			path);
    144		close(fd);
    145		return NULL;
    146	}
    147
    148	elf_class = ehdr->e_ident[EI_CLASS];
    149	switch (elf_class) {
    150	case ELFCLASS32:
    151	case ELFCLASS64:
    152		break;
    153	default:
    154		fprintf(stderr, "%s: '%s' has invalid ELF class\n",
    155			program_name, path);
    156		close(fd);
    157		return NULL;
    158	}
    159
    160	switch (ehdr->e_ident[EI_DATA]) {
    161	case ELFDATA2LSB:
    162	case ELFDATA2MSB:
    163		need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER;
    164		break;
    165	default:
    166		fprintf(stderr, "%s: '%s' has invalid ELF data order\n",
    167			program_name, path);
    168		close(fd);
    169		return NULL;
    170	}
    171
    172	if (swap_uint16(ehdr->e_machine) != EM_MIPS) {
    173		fprintf(stderr,
    174			"%s: '%s' has invalid ELF machine (expected EM_MIPS)\n",
    175			program_name, path);
    176		close(fd);
    177		return NULL;
    178	} else if (swap_uint16(ehdr->e_type) != ET_DYN) {
    179		fprintf(stderr,
    180			"%s: '%s' has invalid ELF type (expected ET_DYN)\n",
    181			program_name, path);
    182		close(fd);
    183		return NULL;
    184	}
    185
    186	*_size = stat.st_size;
    187	close(fd);
    188	return addr;
    189}
    190
    191static bool patch_vdso(const char *path, void *vdso)
    192{
    193	if (elf_class == ELFCLASS64)
    194		return patch_vdso64(path, vdso);
    195	else
    196		return patch_vdso32(path, vdso);
    197}
    198
    199static bool get_symbols(const char *path, void *vdso)
    200{
    201	if (elf_class == ELFCLASS64)
    202		return get_symbols64(path, vdso);
    203	else
    204		return get_symbols32(path, vdso);
    205}
    206
    207int main(int argc, char **argv)
    208{
    209	const char *dbg_vdso_path, *vdso_path, *out_path;
    210	void *dbg_vdso, *vdso;
    211	size_t dbg_vdso_size, vdso_size, i;
    212
    213	program_name = argv[0];
    214
    215	if (argc < 4 || argc > 5) {
    216		fprintf(stderr,
    217			"Usage: %s <debug VDSO> <stripped VDSO> <output file> [<name>]\n",
    218			program_name);
    219		return EXIT_FAILURE;
    220	}
    221
    222	dbg_vdso_path = argv[1];
    223	vdso_path = argv[2];
    224	out_path = argv[3];
    225	vdso_name = (argc > 4) ? argv[4] : "";
    226
    227	dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size);
    228	if (!dbg_vdso)
    229		return EXIT_FAILURE;
    230
    231	vdso = map_vdso(vdso_path, &vdso_size);
    232	if (!vdso)
    233		return EXIT_FAILURE;
    234
    235	/* Patch both the VDSOs' ABI flags sections. */
    236	if (!patch_vdso(dbg_vdso_path, dbg_vdso))
    237		return EXIT_FAILURE;
    238	if (!patch_vdso(vdso_path, vdso))
    239		return EXIT_FAILURE;
    240
    241	if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) {
    242		fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
    243			dbg_vdso_path, strerror(errno));
    244		return EXIT_FAILURE;
    245	} else if (msync(vdso, vdso_size, MS_SYNC) != 0) {
    246		fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
    247			vdso_path, strerror(errno));
    248		return EXIT_FAILURE;
    249	}
    250
    251	out_file = fopen(out_path, "w");
    252	if (!out_file) {
    253		fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
    254			out_path, strerror(errno));
    255		return EXIT_FAILURE;
    256	}
    257
    258	fprintf(out_file, "/* Automatically generated - do not edit */\n");
    259	fprintf(out_file, "#include <linux/linkage.h>\n");
    260	fprintf(out_file, "#include <linux/mm.h>\n");
    261	fprintf(out_file, "#include <asm/vdso.h>\n");
    262	fprintf(out_file, "static int vdso_mremap(\n");
    263	fprintf(out_file, "	const struct vm_special_mapping *sm,\n");
    264	fprintf(out_file, "	struct vm_area_struct *new_vma)\n");
    265	fprintf(out_file, "{\n");
    266	fprintf(out_file, "	current->mm->context.vdso =\n");
    267	fprintf(out_file, "	(void *)(new_vma->vm_start);\n");
    268	fprintf(out_file, "	return 0;\n");
    269	fprintf(out_file, "}\n");
    270
    271	/* Write out the stripped VDSO data. */
    272	fprintf(out_file,
    273		"static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
    274		vdso_size);
    275	for (i = 0; i < vdso_size; i++) {
    276		if (!(i % 10))
    277			fprintf(out_file, "\n\t");
    278		fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]);
    279	}
    280	fprintf(out_file, "\n};\n");
    281
    282	/* Preallocate a page array. */
    283	fprintf(out_file,
    284		"static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n",
    285		vdso_size);
    286
    287	fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
    288		(vdso_name[0]) ? "_" : "", vdso_name);
    289	fprintf(out_file, "\t.data = vdso_data,\n");
    290	fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
    291	fprintf(out_file, "\t.mapping = {\n");
    292	fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
    293	fprintf(out_file, "\t\t.pages = vdso_pages,\n");
    294	fprintf(out_file, "\t\t.mremap = vdso_mremap,\n");
    295	fprintf(out_file, "\t},\n");
    296
    297	/* Calculate and write symbol offsets to <output file> */
    298	if (!get_symbols(dbg_vdso_path, dbg_vdso)) {
    299		unlink(out_path);
    300		fclose(out_file);
    301		return EXIT_FAILURE;
    302	}
    303
    304	fprintf(out_file, "};\n");
    305	fclose(out_file);
    306
    307	return EXIT_SUCCESS;
    308}