Changeset View
Changeset View
Standalone View
Standalone View
libexec/rtld-elf/map_object.c
| Show First 20 Lines • Show All 339 Lines • ▼ Show 20 Lines | error: | ||||
| if (note_map != NULL && note_map != MAP_FAILED) | if (note_map != NULL && note_map != MAP_FAILED) | ||||
| munmap(note_map, note_map_len); | munmap(note_map, note_map_len); | ||||
| if (!phdr_in_zero_page(hdr)) | if (!phdr_in_zero_page(hdr)) | ||||
| munmap(phdr, hdr->e_phnum * sizeof(phdr[0])); | munmap(phdr, hdr->e_phnum * sizeof(phdr[0])); | ||||
| munmap(hdr, PAGE_SIZE); | munmap(hdr, PAGE_SIZE); | ||||
| 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) | ||||
| { | { | ||||
| Elf_Ehdr *hdr; | Elf_Ehdr *hdr; | ||||
| Elf_Phdr *phdr; | Elf_Phdr *phdr; | ||||
| /* Make sure file has enough data for the ELF header */ | /* Make sure file has enough data for the ELF header */ | ||||
| if (sbp != NULL && sbp->st_size < (off_t)sizeof(Elf_Ehdr)) { | if (sbp != NULL && sbp->st_size < (off_t)sizeof(Elf_Ehdr)) { | ||||
| _rtld_error("%s: invalid file format", path); | _rtld_error("%s: invalid file format", path); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, | hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, | ||||
| fd, 0); | fd, 0); | ||||
| if (hdr == MAP_FAILED) { | if (hdr == MAP_FAILED) { | ||||
| _rtld_error("%s: read error: %s", path, rtld_strerror(errno)); | _rtld_error("%s: read error: %s", path, rtld_strerror(errno)); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| /* 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 { | ||||
| phdr = mmap(NULL, hdr->e_phnum * sizeof(phdr[0]), | phdr = mmap(NULL, hdr->e_phnum * sizeof(phdr[0]), | ||||
| PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, fd, | PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, fd, | ||||
| hdr->e_phoff); | hdr->e_phoff); | ||||
| if (phdr == MAP_FAILED) { | if (phdr == MAP_FAILED) { | ||||
| _rtld_error("%s: error mapping phdr: %s", path, | _rtld_error("%s: error mapping phdr: %s", path, | ||||
| ▲ Show 20 Lines • Show All 96 Lines • Show Last 20 Lines | |||||