예제 #1
0
static int elf_read_phdr(const char *buf, size_t len, struct elf_info *elf_info,
			 int idx)
{
	/* Override the const in proghdrs, we are the ones doing the loading. */
	struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
	const char *pbuf;
	struct elf_phdr *buf_phdr;

	pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
	buf_phdr = (struct elf_phdr *) pbuf;

	phdr->p_type   = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
	phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset);
	phdr->p_paddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr);
	phdr->p_vaddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr);
	phdr->p_flags  = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);

	/*
	 * The following fields have a type equivalent to Elf_Addr
	 * both in 32 bit and 64 bit ELF.
	 */
	phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz);
	phdr->p_memsz  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz);
	phdr->p_align  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align);

	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
}
예제 #2
0
static int build_mem_elf64_phdr(const char *buf, off_t len,
	struct mem_ehdr *ehdr, int idx)
{
	struct mem_phdr *phdr;
	const char *pbuf;
	Elf64_Phdr lphdr;
	pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr));
	phdr = &ehdr->e_phdr[idx];
	memcpy(&lphdr, pbuf, sizeof(lphdr));

	if (	(elf64_to_cpu(ehdr, lphdr.p_filesz) > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lphdr.p_memsz)  > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lphdr.p_offset) > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lphdr.p_paddr)  > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lphdr.p_vaddr)  > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lphdr.p_align)  > UINT64_MAX))
	{
		fprintf(stderr, "Program segment size out of range\n");
		return -1;
	}

	phdr->p_type   = elf32_to_cpu(ehdr, lphdr.p_type);
	phdr->p_paddr  = elf64_to_cpu(ehdr, lphdr.p_paddr);
	phdr->p_vaddr  = elf64_to_cpu(ehdr, lphdr.p_vaddr);
	phdr->p_filesz = elf64_to_cpu(ehdr, lphdr.p_filesz);
	phdr->p_memsz  = elf64_to_cpu(ehdr, lphdr.p_memsz);
	phdr->p_offset = elf64_to_cpu(ehdr, lphdr.p_offset);
	phdr->p_flags  = elf32_to_cpu(ehdr, lphdr.p_flags);
	phdr->p_align  = elf64_to_cpu(ehdr, lphdr.p_align);

	return 0;
}
예제 #3
0
파일: kexec_elf_64.c 프로젝트: dznm/linux
static int elf_read_shdr(const char *buf, size_t len, struct elf_info *elf_info,
			 int idx)
{
	struct elf_shdr *shdr = &elf_info->sechdrs[idx];
	const struct elfhdr *ehdr = elf_info->ehdr;
	const char *sbuf;
	struct elf_shdr *buf_shdr;

	sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
	buf_shdr = (struct elf_shdr *) sbuf;

	shdr->sh_name      = elf32_to_cpu(ehdr, buf_shdr->sh_name);
	shdr->sh_type      = elf32_to_cpu(ehdr, buf_shdr->sh_type);
	shdr->sh_addr      = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
	shdr->sh_offset    = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
	shdr->sh_link      = elf32_to_cpu(ehdr, buf_shdr->sh_link);
	shdr->sh_info      = elf32_to_cpu(ehdr, buf_shdr->sh_info);

	/*
	 * The following fields have a type equivalent to Elf_Addr
	 * both in 32 bit and 64 bit ELF.
	 */
	shdr->sh_flags     = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
	shdr->sh_size      = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
	shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
	shdr->sh_entsize   = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);

	return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
}
예제 #4
0
static struct mem_sym elf_sym(struct mem_ehdr *ehdr, const unsigned char *ptr)
{
	struct mem_sym sym = { };
	if (ehdr->ei_class == ELFCLASS32) {
		Elf32_Sym lsym;
		memcpy(&lsym, ptr, sizeof(lsym));
		sym.st_name  = elf32_to_cpu(ehdr, lsym.st_name);
		sym.st_value = elf32_to_cpu(ehdr, lsym.st_value);
		sym.st_size  = elf32_to_cpu(ehdr, lsym.st_size);
		sym.st_info  = lsym.st_info;
		sym.st_other = lsym.st_other;
		sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx);
	}
	else if (ehdr->ei_class == ELFCLASS64) {
		Elf64_Sym lsym;
		memcpy(&lsym, ptr, sizeof(lsym));
		sym.st_name  = elf32_to_cpu(ehdr, lsym.st_name);
		sym.st_value = elf64_to_cpu(ehdr, lsym.st_value);
		sym.st_size  = elf64_to_cpu(ehdr, lsym.st_size);
		sym.st_info  = lsym.st_info;
		sym.st_other = lsym.st_other;
		sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx);
	}
	else {
		die("Bad elf class");
	}
	return sym;
}
static void read_nhdr(const struct mem_ehdr *ehdr,
	ElfNN_Nhdr *hdr, const unsigned char *note)
{
	memcpy(hdr, note, sizeof(*hdr));
	hdr->n_namesz = elf32_to_cpu(ehdr, hdr->n_namesz);
	hdr->n_descsz = elf32_to_cpu(ehdr, hdr->n_descsz);
	hdr->n_type   = elf32_to_cpu(ehdr, hdr->n_type);

}
예제 #6
0
static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
{
	struct elfhdr *buf_ehdr;

	if (len < sizeof(*buf_ehdr)) {
		pr_debug("Buffer is too small to hold ELF header.\n");
		return -ENOEXEC;
	}

	memset(ehdr, 0, sizeof(*ehdr));
	memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
	if (!elf_is_elf_file(ehdr)) {
		pr_debug("No ELF header magic.\n");
		return -ENOEXEC;
	}

	if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
		pr_debug("Not a supported ELF class.\n");
		return -1;
	} else  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
		ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
		pr_debug("Not a supported ELF data format.\n");
		return -ENOEXEC;
	}

	buf_ehdr = (struct elfhdr *) buf;
	if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
		pr_debug("Bad ELF header size.\n");
		return -ENOEXEC;
	}

	ehdr->e_type      = elf16_to_cpu(ehdr, buf_ehdr->e_type);
	ehdr->e_machine   = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
	ehdr->e_version   = elf32_to_cpu(ehdr, buf_ehdr->e_version);
	ehdr->e_entry     = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry);
	ehdr->e_phoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff);
	ehdr->e_shoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff);
	ehdr->e_flags     = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
	ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
	ehdr->e_phnum     = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
	ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
	ehdr->e_shnum     = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);

	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
}
예제 #7
0
static struct mem_rela elf_rel(struct mem_ehdr *ehdr, const unsigned char *ptr)
{
	struct mem_rela rela = { };
	if (ehdr->ei_class == ELFCLASS32) {
		Elf32_Rel lrel;
		memcpy(&lrel, ptr, sizeof(lrel));
		rela.r_offset = elf32_to_cpu(ehdr, lrel.r_offset);
		rela.r_sym    = ELF32_R_SYM(elf32_to_cpu(ehdr, lrel.r_info));
		rela.r_type   = ELF32_R_TYPE(elf32_to_cpu(ehdr, lrel.r_info));
		rela.r_addend = 0;
	}
	else if (ehdr->ei_class == ELFCLASS64) {
		Elf64_Rel lrel;
		memcpy(&lrel, ptr, sizeof(lrel));
		rela.r_offset = elf64_to_cpu(ehdr, lrel.r_offset);
		rela.r_sym    = ELF64_R_SYM(elf64_to_cpu(ehdr, lrel.r_info));
		rela.r_type   = ELF64_R_TYPE(elf64_to_cpu(ehdr, lrel.r_info));
		rela.r_addend = 0;
	}
	else {
		die("Bad elf class");
	}
	return rela;
}
static int build_mem_elf32_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr)
{
	Elf32_Ehdr lehdr;
	if (len < sizeof(lehdr)) {
		/* Buffer is to small to be an elf executable */
		if (probe_debug) {
			fprintf(stderr, "Buffer is to small to hold ELF header\n");
		}
		return -1;
	}
	memcpy(&lehdr, buf, sizeof(lehdr));
	if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf32_Ehdr)) {
		/* Invalid Elf header size */
		if (probe_debug) {
			fprintf(stderr, "Bad ELF header size\n");
		}
		return -1;
	}
	if (elf32_to_cpu(ehdr, lehdr.e_entry) > UINT32_MAX) {
		/* entry is to large */
		if (probe_debug) {
			fprintf(stderr, "ELF e_entry to large\n");
		}
		return -1;
	}
	if (elf32_to_cpu(ehdr, lehdr.e_phoff) > UINT32_MAX) {
		/* phoff is to large */
		if (probe_debug) {
			fprintf(stderr, "ELF e_phoff to large\n");
		}
		return -1;
	}
	if (elf32_to_cpu(ehdr, lehdr.e_shoff) > UINT32_MAX) {
		/* shoff is to large */
		if (probe_debug) {
			fprintf(stderr, "ELF e_shoff to large\n");
		}
		return -1;
	}
	ehdr->e_type      = elf16_to_cpu(ehdr, lehdr.e_type);
	ehdr->e_machine   = elf16_to_cpu(ehdr, lehdr.e_machine);
	ehdr->e_version   = elf32_to_cpu(ehdr, lehdr.e_version);
	ehdr->e_entry     = elf32_to_cpu(ehdr, lehdr.e_entry);
	ehdr->e_phoff     = elf32_to_cpu(ehdr, lehdr.e_phoff);
	ehdr->e_shoff     = elf32_to_cpu(ehdr, lehdr.e_shoff);
	ehdr->e_flags     = elf32_to_cpu(ehdr, lehdr.e_flags);
	ehdr->e_phnum     = elf16_to_cpu(ehdr, lehdr.e_phnum);
	ehdr->e_shnum     = elf16_to_cpu(ehdr, lehdr.e_shnum);
	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, lehdr.e_shstrndx);

	if ((ehdr->e_phnum > 0) &&
		(elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf32_Phdr)))
	{
		/* Invalid program header size */
		if (probe_debug) {
			fprintf(stderr, "ELF bad program header size\n");
		}
		return -1;
	}
	if ((ehdr->e_shnum > 0) &&
		(elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf32_Shdr)))
	{
		/* Invalid section header size */
		if (probe_debug) {
			fprintf(stderr, "ELF bad section header size\n");
		}
		return -1;
	}

	return 0;
}
static int build_mem_elf64_shdr(const char *buf, off_t len,
	struct mem_ehdr *ehdr, int idx)
{
	struct mem_shdr *shdr;
	const char *sbuf;
	int size_ok;
	Elf64_Shdr lshdr;
	sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr));
	shdr = &ehdr->e_shdr[idx];
	memcpy(&lshdr, sbuf, sizeof(lshdr));

	if (	(elf64_to_cpu(ehdr, lshdr.sh_flags)     > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lshdr.sh_addr)      > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lshdr.sh_offset)    > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lshdr.sh_size)      > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lshdr.sh_addralign) > UINT64_MAX) ||
		(elf64_to_cpu(ehdr, lshdr.sh_entsize)   > UINT64_MAX))
	{
		fprintf(stderr, "Program section size out of range\n");
		return -1;
	}

	shdr->sh_name      = elf32_to_cpu(ehdr, lshdr.sh_name);
	shdr->sh_type      = elf32_to_cpu(ehdr, lshdr.sh_type);
	shdr->sh_flags     = elf64_to_cpu(ehdr, lshdr.sh_flags);
	shdr->sh_addr      = elf64_to_cpu(ehdr, lshdr.sh_addr);
	shdr->sh_offset    = elf64_to_cpu(ehdr, lshdr.sh_offset);
	shdr->sh_size      = elf64_to_cpu(ehdr, lshdr.sh_size);
	shdr->sh_link      = elf32_to_cpu(ehdr, lshdr.sh_link);
	shdr->sh_info      = elf32_to_cpu(ehdr, lshdr.sh_info);
	shdr->sh_addralign = elf64_to_cpu(ehdr, lshdr.sh_addralign);
	shdr->sh_entsize   = elf64_to_cpu(ehdr, lshdr.sh_entsize);

	/* Now verify sh_entsize */
	size_ok = 0;
	switch(shdr->sh_type) {
	case SHT_SYMTAB:
		size_ok = shdr->sh_entsize == sizeof(Elf64_Sym);
		break;
	case SHT_RELA:
		size_ok = shdr->sh_entsize == sizeof(Elf64_Rela);
		break;
	case SHT_DYNAMIC:
		size_ok = shdr->sh_entsize == sizeof(Elf64_Dyn);
		break;
	case SHT_REL:
		size_ok = shdr->sh_entsize == sizeof(Elf64_Rel);
		break;
	case SHT_NOTE:
	case SHT_NULL:
	case SHT_PROGBITS:
	case SHT_HASH:
	case SHT_NOBITS:
	default:
		/* This is a section whose entsize requirements
		 * I don't care about.  If I don't know about
		 * the section I can't care about it's entsize
		 * requirements.
		 */
		size_ok = 1;
		break;
	}
	if (!size_ok) {
		fprintf(stderr, "Bad section header(%x) entsize: %ld\n",
			shdr->sh_type, shdr->sh_entsize);
		return -1;
	}
	return 0;
}