[SLOF] [PATCH v2 1/3] elf: Implement elf_get_file_size to determine size of an ELF image
Stefan Berger
stefanb at linux.ibm.com
Sat May 9 07:01:24 AEST 2020
On 5/7/20 9:07 PM, Alexey Kardashevskiy wrote:
>
> On 02/04/2020 01:57, Stefan Berger wrote:
>> From: Stefan Berger <stefanb at linux.ibm.com>
>>
>> Implement elf_get_file_size to determine the size of an ELF image
>> that has been loaded into a buffer much larger than the actual size
>> of the original file. We determine the size by searching for the
>> farthest offset declared by the ELF headers.
>>
>> Signed-off-by: Stefan Berger <stefanb at linux.ibm.com>
>> ---
>> include/helpers.h | 2 ++
>> include/libelf.h | 14 ++++++++++
>> lib/libelf/elf.c | 26 ++++++++++++++++++
>> lib/libelf/elf32.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
>> lib/libelf/elf64.c | 56 ++++++++++++++++++++++++++++++++++++++
>> 5 files changed, 166 insertions(+)
>>
>> diff --git a/include/helpers.h b/include/helpers.h
>> index 47b2674..112184f 100644
>> --- a/include/helpers.h
>> +++ b/include/helpers.h
>> @@ -51,5 +51,7 @@ extern unsigned long SLOF_get_vtpm_unit(void);
>> const typeof(((type *)0)->member)* struct_ptr = (ptr); \
>> (type *)((char *)struct_ptr - offset_of(type, member)); })
>> #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
>> +#define ROUNDUP(x,v) ((((x) + ((v) - 1)) / (v)) * (v))
>> +#define MAX(x,y) ((x) > (y) ? (x) : (y))
>>
>> #endif
>> diff --git a/include/libelf.h b/include/libelf.h
>> index 5fbf279..48ff4d7 100644
>> --- a/include/libelf.h
>> +++ b/include/libelf.h
>> @@ -96,4 +96,18 @@ void elf_relocate64(void *file_addr, signed long offset);
>>
>> int elf_forth_claim(void *addr, long size);
>>
>> +long elf_get_file_size(const void *buffer, const long buffer_size);
>> +long elf_get_file_size32(const void *buffer, const long buffer_size);
>> +long elf_get_file_size64(const void *buffer, const long buffer_size);
>> +
>> +#ifdef __BIG_ENDIAN__
>> +#define elf64_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2MSB ? (x) : bswap_64(x))
>> +#define elf32_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2MSB ? (x) : bswap_32(x))
>> +#define elf16_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2MSB ? (x) : bswap_16(x))
>> +#else
>> +#define elf64_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2LSB ? (x) : bswap_64(x))
>> +#define elf32_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2LSB ? (x) : bswap_32(x))
>> +#define elf16_to_cpu(x, ehdr) ((ehdr)->ei_data == ELFDATA2LSB ? (x) : bswap_16(x))
>> +#endif
>> +
>> #endif /* __LIBELF_H */
>> diff --git a/lib/libelf/elf.c b/lib/libelf/elf.c
>> index 5204bc3..d368454 100644
>> --- a/lib/libelf/elf.c
>> +++ b/lib/libelf/elf.c
>> @@ -196,3 +196,29 @@ elf_get_base_addr(void *file_addr)
>>
>> return -1;
>> }
>> +
>> +/**
>> + * Get the file size of the ELF image that has been loaded into a
>> + * buffer larger than the size of the file
>> + * @return The size of the ELF image or < 0 for error
>> + */
>> +long elf_get_file_size(const void *buffer, const long buffer_size)
>> +{
>> + const struct ehdr *ehdr = (const struct ehdr *)buffer;
>> +
>> + if (buffer_size < sizeof(struct ehdr))
>> + return -1;
>> +
>> + /* check if it is an ELF image at all */
>> + if (cpu_to_be32(ehdr->ei_ident) != 0x7f454c46)
>> + return -1;
>> +
>> + switch (ehdr->ei_class) {
>> + case 1:
>> + return elf_get_file_size32(buffer, buffer_size);
>> + case 2:
>> + return elf_get_file_size64(buffer, buffer_size);
>> + }
>> +
>> + return -1;
>> +}
>> diff --git a/lib/libelf/elf32.c b/lib/libelf/elf32.c
>> index fea5cf4..7ea85f0 100644
>> --- a/lib/libelf/elf32.c
>> +++ b/lib/libelf/elf32.c
>> @@ -17,6 +17,7 @@
>> #include <string.h>
>> #include <libelf.h>
>> #include <byteorder.h>
>> +#include <helpers.h>
>>
>> struct ehdr32 {
>> uint32_t ei_ident;
>> @@ -50,6 +51,18 @@ struct phdr32 {
>> uint32_t p_align;
>> };
>>
>> +struct shdr32 {
>> + uint32_t sh_name;
>> + uint32_t sh_type;
>> + uint32_t sh_flags;
>> + uint32_t sh_addr;
>> + uint32_t sh_offset;
>> + uint32_t sh_size;
>> + uint32_t sh_link;
>> + uint32_t sh_info;
>> + uint32_t sh_addralign;
>> + uint32_t sh_entsize;
>> +};
>>
>> static struct phdr32*
>> get_phdr32(void *file_addr)
>> @@ -191,3 +204,58 @@ elf_byteswap_header32(void *file_addr)
>> phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
>> }
>> }
>> +
>> +/*
>> + * Determine the size of an ELF image that has been loaded into
>> + * a buffer larger than its size. We search all program headers
>> + * and sections for the one that shows the farthest extent of the
>> + * file.
>> + * @return Return -1 on error, size of file otherwise.
>> + */
>> +long elf_get_file_size32(const void *buffer, const long buffer_size)
>> +{
>> + const struct ehdr32 *ehdr = (const struct ehdr32 *) buffer;
>> + const uint8_t *buffer_end = buffer + buffer_size;
>> + const struct phdr32 *phdr;
>> + const struct shdr32 *shdr;
>> + long elf_size = -1;
>> + uint16_t entsize;
>> + unsigned i;
>> +
>> + if (buffer_size < sizeof(struct ehdr) || ehdr->e_ehsize != 52)
> What is 52? sizeof(struct ehdr32)? Why "!=" rather ">=" ?
Right, it's sizeof(struct ehdr32). I will repost this series.
More information about the SLOF
mailing list