hw/elf_ops.h: switch to ssize_t for elf loader return type

Until now, int was used as the return type for all the ELF
loader related functions. The returned value is the sum of all loaded
program headers "MemSize" fields.

Because of the overflow check in elf_ops.h, trying to load an ELF bigger
than INT_MAX will fail. Switch to ssize_t to remove this limitation.

Signed-off-by: Luc Michel <lmichel@kalray.eu>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Message-Id: <20211014194325.19917-1-lmichel@kalray.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Luc Michel 2021-10-14 21:43:25 +02:00 committed by Richard Henderson
parent b84722cf44
commit 8975eb891f
3 changed files with 74 additions and 71 deletions

View File

@ -326,7 +326,7 @@ static void *load_at(int fd, off_t offset, size_t size)
#define SZ 64 #define SZ 64
#include "hw/elf_ops.h" #include "hw/elf_ops.h"
const char *load_elf_strerror(int error) const char *load_elf_strerror(ssize_t error)
{ {
switch (error) { switch (error) {
case 0: case 0:
@ -402,12 +402,12 @@ fail:
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, ssize_t load_elf(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int elf_machine, int clear_lsb, int data_swab) int elf_machine, int clear_lsb, int data_swab)
{ {
return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque, return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, pflags, big_endian, pentry, lowaddr, highaddr, pflags, big_endian,
@ -415,12 +415,13 @@ int load_elf(const char *filename,
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_as(const char *filename, ssize_t load_elf_as(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int elf_machine, int clear_lsb, int data_swab, AddressSpace *as) int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as)
{ {
return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque, return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, pflags, big_endian, pentry, lowaddr, highaddr, pflags, big_endian,
@ -428,13 +429,13 @@ int load_elf_as(const char *filename,
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram(const char *filename, ssize_t load_elf_ram(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
int elf_machine, int clear_lsb, int data_swab, int big_endian, int elf_machine, int clear_lsb,
AddressSpace *as, bool load_rom) int data_swab, AddressSpace *as, bool load_rom)
{ {
return load_elf_ram_sym(filename, elf_note_fn, return load_elf_ram_sym(filename, elf_note_fn,
translate_fn, translate_opaque, translate_fn, translate_opaque,
@ -444,16 +445,17 @@ int load_elf_ram(const char *filename,
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram_sym(const char *filename, ssize_t load_elf_ram_sym(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, uint64_t *lowaddr, uint64_t *highaddr,
int big_endian, int elf_machine, uint32_t *pflags, int big_endian, int elf_machine,
int clear_lsb, int data_swab, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb) AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
{ {
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED; int fd, data_order, target_data_order, must_swab;
ssize_t ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT]; uint8_t e_ident[EI_NIDENT];
fd = open(filename, O_RDONLY | O_BINARY); fd = open(filename, O_RDONLY | O_BINARY);

View File

@ -312,25 +312,26 @@ static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
return nhdr; return nhdr;
} }
static int glue(load_elf, SZ)(const char *name, int fd, static ssize_t glue(load_elf, SZ)(const char *name, int fd,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, void *translate_opaque,
int must_swab, uint64_t *pentry, int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, uint64_t *lowaddr, uint64_t *highaddr,
uint32_t *pflags, int elf_machine, uint32_t *pflags, int elf_machine,
int clear_lsb, int data_swab, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, AddressSpace *as, bool load_rom,
symbol_fn_t sym_cb) symbol_fn_t sym_cb)
{ {
struct elfhdr ehdr; struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph; struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size; int size, i;
ssize_t total_size;
elf_word mem_size, file_size, data_offset; elf_word mem_size, file_size, data_offset;
uint64_t addr, low = (uint64_t)-1, high = 0; uint64_t addr, low = (uint64_t)-1, high = 0;
GMappedFile *mapped_file = NULL; GMappedFile *mapped_file = NULL;
uint8_t *data = NULL; uint8_t *data = NULL;
int ret = ELF_LOAD_FAILED; ssize_t ret = ELF_LOAD_FAILED;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto fail; goto fail;
@ -482,7 +483,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
} }
} }
if (mem_size > INT_MAX - total_size) { if (mem_size > SSIZE_MAX - total_size) {
ret = ELF_LOAD_TOO_BIG; ret = ELF_LOAD_TOO_BIG;
goto fail; goto fail;
} }

View File

@ -90,7 +90,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ARCH -3 #define ELF_LOAD_WRONG_ARCH -3
#define ELF_LOAD_WRONG_ENDIAN -4 #define ELF_LOAD_WRONG_ENDIAN -4
#define ELF_LOAD_TOO_BIG -5 #define ELF_LOAD_TOO_BIG -5
const char *load_elf_strerror(int error); const char *load_elf_strerror(ssize_t error);
/** load_elf_ram_sym: /** load_elf_ram_sym:
* @filename: Path of ELF file * @filename: Path of ELF file
@ -128,48 +128,48 @@ const char *load_elf_strerror(int error);
typedef void (*symbol_fn_t)(const char *st_name, int st_info, typedef void (*symbol_fn_t)(const char *st_name, int st_info,
uint64_t st_value, uint64_t st_size); uint64_t st_value, uint64_t st_size);
int load_elf_ram_sym(const char *filename, ssize_t load_elf_ram_sym(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, uint64_t *lowaddr, uint64_t *highaddr,
int big_endian, int elf_machine, uint32_t *pflags, int big_endian, int elf_machine,
int clear_lsb, int data_swab, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb); AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
/** load_elf_ram: /** load_elf_ram:
* Same as load_elf_ram_sym(), but doesn't allow the caller to specify a * Same as load_elf_ram_sym(), but doesn't allow the caller to specify a
* symbol callback function * symbol callback function
*/ */
int load_elf_ram(const char *filename, ssize_t load_elf_ram(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
int elf_machine, int clear_lsb, int data_swab, int big_endian, int elf_machine, int clear_lsb,
AddressSpace *as, bool load_rom); int data_swab, AddressSpace *as, bool load_rom);
/** load_elf_as: /** load_elf_as:
* Same as load_elf_ram(), but always loads the elf as ROM * Same as load_elf_ram(), but always loads the elf as ROM
*/ */
int load_elf_as(const char *filename, ssize_t load_elf_as(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int elf_machine, int clear_lsb, int data_swab, int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as); AddressSpace *as);
/** load_elf: /** load_elf:
* Same as load_elf_as(), but doesn't allow the caller to specify an * Same as load_elf_as(), but doesn't allow the caller to specify an
* AddressSpace. * AddressSpace.
*/ */
int load_elf(const char *filename, ssize_t load_elf(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, uint32_t *pflags, int big_endian, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int elf_machine, int clear_lsb, int data_swab); int elf_machine, int clear_lsb, int data_swab);
/** load_elf_hdr: /** load_elf_hdr:
* @filename: Path of ELF file * @filename: Path of ELF file