rtld: extract header validation into new helper check_elf_headers()

Reviewed by:	emaste
Discussed with:	jrtc27
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D32960
This commit is contained in:
Konstantin Belousov 2021-11-11 19:51:26 +02:00
parent 01c77a436e
commit 63fc4e820c
2 changed files with 35 additions and 26 deletions

View File

@ -345,6 +345,39 @@ map_object(int fd, const char *path, const struct stat *sb)
return (NULL); return (NULL);
} }
bool
check_elf_headers(const Elf_Ehdr *hdr, const char *path)
{
if (!IS_ELF(*hdr)) {
_rtld_error("%s: invalid file format", path);
return (false);
}
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
_rtld_error("%s: unsupported file layout", path);
return (false);
}
if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
hdr->e_version != EV_CURRENT) {
_rtld_error("%s: unsupported file version", path);
return (false);
}
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
_rtld_error("%s: unsupported file type", path);
return (false);
}
if (hdr->e_machine != ELF_TARG_MACH) {
_rtld_error("%s: unsupported machine", path);
return (false);
}
if (hdr->e_phentsize != sizeof(Elf_Phdr)) {
_rtld_error(
"%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path);
return (false);
}
return (true);
}
static Elf_Ehdr * static Elf_Ehdr *
get_elf_header(int fd, const char *path, const struct stat *sbp, get_elf_header(int fd, const char *path, const struct stat *sbp,
Elf_Phdr **phdr_p) Elf_Phdr **phdr_p)
@ -366,39 +399,14 @@ get_elf_header(int fd, const char *path, const struct stat *sbp,
} }
/* Make sure the file is valid */ /* Make sure the file is valid */
if (!IS_ELF(*hdr)) { if (!check_elf_headers(hdr, path))
_rtld_error("%s: invalid file format", path);
goto error; goto error;
}
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
_rtld_error("%s: unsupported file layout", path);
goto error;
}
if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
hdr->e_version != EV_CURRENT) {
_rtld_error("%s: unsupported file version", path);
goto error;
}
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
_rtld_error("%s: unsupported file type", path);
goto error;
}
if (hdr->e_machine != ELF_TARG_MACH) {
_rtld_error("%s: unsupported machine", path);
goto error;
}
/* /*
* We rely on the program header being in the first page. This is * We rely on the program header being in the first page. This is
* not strictly required by the ABI specification, but it seems to * not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably. * always true in practice. And, it simplifies things considerably.
*/ */
if (hdr->e_phentsize != sizeof(Elf_Phdr)) {
_rtld_error(
"%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path);
goto error;
}
if (phdr_in_zero_page(hdr)) { if (phdr_in_zero_page(hdr)) {
phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff); phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff);
} else { } else {

View File

@ -405,6 +405,7 @@ void free_tls_offset(Obj_Entry *obj);
const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long); const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
int convert_prot(int elfflags); int convert_prot(int elfflags);
void *_get_tp(void); /* libc implementation */ void *_get_tp(void); /* libc implementation */
bool check_elf_headers(const Elf_Ehdr *hdr, const char *path);
/* /*
* MD function declarations. * MD function declarations.