Skip to content

Commit

Permalink
linux-user: Use ImageSource in load_elf_image
Browse files Browse the repository at this point in the history
Change parse_elf_properties as well, as the bprm_buf argument
ties the two functions closely.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Oct 30, 2023
1 parent 40d487e commit 3bd0238
Showing 1 changed file with 49 additions and 79 deletions.
128 changes: 49 additions & 79 deletions linux-user/elfload.c
Original file line number Diff line number Diff line change
Expand Up @@ -3102,10 +3102,9 @@ static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
}

/* Process NT_GNU_PROPERTY_TYPE_0. */
static bool parse_elf_properties(int image_fd,
static bool parse_elf_properties(const ImageSource *src,
struct image_info *info,
const struct elf_phdr *phdr,
char bprm_buf[BPRM_BUF_SIZE],
Error **errp)
{
union {
Expand Down Expand Up @@ -3133,14 +3132,8 @@ static bool parse_elf_properties(int image_fd,
return false;
}

if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
memcpy(&note, bprm_buf + phdr->p_offset, n);
} else {
ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
if (len != n) {
error_setg_errno(errp, errno, "Error reading file header");
return false;
}
if (!imgsrc_read(&note, phdr->p_offset, n, src, errp)) {
return false;
}

/*
Expand Down Expand Up @@ -3186,30 +3179,34 @@ static bool parse_elf_properties(int image_fd,
}
}

/* Load an ELF image into the address space.
IMAGE_NAME is the filename of the image, to use in error messages.
IMAGE_FD is the open file descriptor for the image.
BPRM_BUF is a copy of the beginning of the file; this of course
contains the elf file header at offset 0. It is assumed that this
buffer is sufficiently aligned to present no problems to the host
in accessing data at aligned offsets within the buffer.
On return: INFO values will be filled in, as necessary or available. */
/**
* load_elf_image: Load an ELF image into the address space.
* @image_name: the filename of the image, to use in error messages.
* @src: the ImageSource from which to read.
* @info: info collected from the loaded image.
* @ehdr: the ELF header, not yet bswapped.
* @pinterp_name: record any PT_INTERP string found.
*
* On return: @info values will be filled in, as necessary or available.
*/

static void load_elf_image(const char *image_name, int image_fd,
static void load_elf_image(const char *image_name, const ImageSource *src,
struct image_info *info, struct elfhdr *ehdr,
char **pinterp_name,
char bprm_buf[BPRM_BUF_SIZE])
char **pinterp_name)
{
struct elf_phdr *phdr;
g_autofree struct elf_phdr *phdr = NULL;
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
int i, retval, prot_exec;
int i, prot_exec;
Error *err = NULL;

/* First of all, some simple consistency checks */
memcpy(ehdr, bprm_buf, sizeof(*ehdr));
/*
* First of all, some simple consistency checks.
* Note that we rely on the bswapped ehdr staying in bprm_buf,
* for later use by load_elf_binary and create_elf_tables.
*/
if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) {
goto exit_errmsg;
}
if (!elf_check_ident(ehdr)) {
error_setg(&err, "Invalid ELF image for this architecture");
goto exit_errmsg;
Expand All @@ -3220,15 +3217,11 @@ static void load_elf_image(const char *image_name, int image_fd,
goto exit_errmsg;
}

i = ehdr->e_phnum * sizeof(struct elf_phdr);
if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
} else {
phdr = (struct elf_phdr *) alloca(i);
retval = pread(image_fd, phdr, i, ehdr->e_phoff);
if (retval != i) {
goto exit_read;
}
phdr = imgsrc_read_alloc(ehdr->e_phoff,
ehdr->e_phnum * sizeof(struct elf_phdr),
src, &err);
if (phdr == NULL) {
goto exit_errmsg;
}
bswap_phdr(phdr, ehdr->e_phnum);

Expand Down Expand Up @@ -3265,25 +3258,18 @@ static void load_elf_image(const char *image_name, int image_fd,
goto exit_errmsg;
}

interp_name = g_malloc(eppnt->p_filesz);

if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
memcpy(interp_name, bprm_buf + eppnt->p_offset,
eppnt->p_filesz);
} else {
retval = pread(image_fd, interp_name, eppnt->p_filesz,
eppnt->p_offset);
if (retval != eppnt->p_filesz) {
goto exit_read;
}
interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz,
src, &err);
if (interp_name == NULL) {
goto exit_errmsg;
}
if (interp_name[eppnt->p_filesz - 1] != 0) {
error_setg(&err, "Invalid PT_INTERP entry");
goto exit_errmsg;
}
*pinterp_name = g_steal_pointer(&interp_name);
} else if (eppnt->p_type == PT_GNU_PROPERTY) {
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
if (!parse_elf_properties(src, info, eppnt, &err)) {
goto exit_errmsg;
}
} else if (eppnt->p_type == PT_GNU_STACK) {
Expand Down Expand Up @@ -3436,9 +3422,9 @@ static void load_elf_image(const char *image_name, int image_fd,
* but no backing file segment.
*/
if (eppnt->p_filesz != 0) {
error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
elf_prot, MAP_PRIVATE | MAP_FIXED,
image_fd, eppnt->p_offset - vaddr_po);
src, eppnt->p_offset - vaddr_po);
if (error == -1) {
goto exit_mmap;
}
Expand Down Expand Up @@ -3470,20 +3456,11 @@ static void load_elf_image(const char *image_name, int image_fd,
#ifdef TARGET_MIPS
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
Mips_elf_abiflags_v0 abiflags;
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");

if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags),
src, &err)) {
goto exit_errmsg;
}
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
memcpy(&abiflags, bprm_buf + eppnt->p_offset,
sizeof(Mips_elf_abiflags_v0));
} else {
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
eppnt->p_offset);
if (retval != sizeof(Mips_elf_abiflags_v0)) {
goto exit_read;
}
}
bswap_mips_abiflags(&abiflags);
info->fp_abi = abiflags.fp_abi;
#endif
Expand All @@ -3496,23 +3473,16 @@ static void load_elf_image(const char *image_name, int image_fd,
}

if (qemu_log_enabled()) {
load_symbols(ehdr, image_fd, load_bias);
load_symbols(ehdr, src->fd, load_bias);
}

debuginfo_report_elf(image_name, image_fd, load_bias);
debuginfo_report_elf(image_name, src->fd, load_bias);

mmap_unlock();

close(image_fd);
close(src->fd);
return;

exit_read:
if (retval >= 0) {
error_setg(&err, "Incomplete read of file header");
} else {
error_setg_errno(&err, errno, "Error reading file header");
}
goto exit_errmsg;
exit_mmap:
error_setg_errno(&err, errno, "Error mapping file");
goto exit_errmsg;
Expand All @@ -3525,6 +3495,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
char bprm_buf[BPRM_BUF_SIZE])
{
struct elfhdr ehdr;
ImageSource src;
int fd, retval;
Error *err = NULL;

Expand All @@ -3542,11 +3513,11 @@ static void load_elf_interp(const char *filename, struct image_info *info,
exit(-1);
}

if (retval < BPRM_BUF_SIZE) {
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
}
src.fd = fd;
src.cache = bprm_buf;
src.cache_size = retval;

load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
load_elf_image(filename, &src, info, &ehdr, NULL);
}

static int symfind(const void *s0, const void *s1)
Expand Down Expand Up @@ -3755,8 +3726,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
#endif

load_elf_image(bprm->filename, bprm->fd, info,
&ehdr, &elf_interpreter, bprm->buf);
load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter);

/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
Expand Down

0 comments on commit 3bd0238

Please sign in to comment.