Allow PT_NOTES segments to be located anywhere in the executable
image. The dynamic linker still requires that program headers of the executable or dso are mapped by a PT_LOAD segment. Reviewed by: emaste, jhb Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D3871
This commit is contained in:
parent
6c775eb64e
commit
bd56d410c4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=289324
@ -88,6 +88,8 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||||||
size_t relro_size;
|
size_t relro_size;
|
||||||
Elf_Addr note_start;
|
Elf_Addr note_start;
|
||||||
Elf_Addr note_end;
|
Elf_Addr note_end;
|
||||||
|
char *note_map;
|
||||||
|
size_t note_map_len;
|
||||||
|
|
||||||
hdr = get_elf_header(fd, path);
|
hdr = get_elf_header(fd, path);
|
||||||
if (hdr == NULL)
|
if (hdr == NULL)
|
||||||
@ -108,6 +110,7 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||||||
relro_size = 0;
|
relro_size = 0;
|
||||||
note_start = 0;
|
note_start = 0;
|
||||||
note_end = 0;
|
note_end = 0;
|
||||||
|
note_map = NULL;
|
||||||
segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
|
segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
|
||||||
stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
|
stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
|
||||||
while (phdr < phlimit) {
|
while (phdr < phlimit) {
|
||||||
@ -150,9 +153,20 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||||||
|
|
||||||
case PT_NOTE:
|
case PT_NOTE:
|
||||||
if (phdr->p_offset > PAGE_SIZE ||
|
if (phdr->p_offset > PAGE_SIZE ||
|
||||||
phdr->p_offset + phdr->p_filesz > PAGE_SIZE)
|
phdr->p_offset + phdr->p_filesz > PAGE_SIZE) {
|
||||||
break;
|
note_map_len = round_page(phdr->p_offset +
|
||||||
note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
|
phdr->p_filesz) - trunc_page(phdr->p_offset);
|
||||||
|
note_map = mmap(NULL, note_map_len, PROT_READ,
|
||||||
|
MAP_PRIVATE, fd, trunc_page(phdr->p_offset));
|
||||||
|
if (note_map == MAP_FAILED) {
|
||||||
|
_rtld_error("%s: error mapping PT_NOTE (%d)", path, errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
note_start = (Elf_Addr)(note_map + phdr->p_offset -
|
||||||
|
trunc_page(phdr->p_offset));
|
||||||
|
} else {
|
||||||
|
note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
|
||||||
|
}
|
||||||
note_end = note_start + phdr->p_filesz;
|
note_end = note_start + phdr->p_filesz;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -295,12 +309,16 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||||||
obj->relro_size = round_page(relro_size);
|
obj->relro_size = round_page(relro_size);
|
||||||
if (note_start < note_end)
|
if (note_start < note_end)
|
||||||
digest_notes(obj, note_start, note_end);
|
digest_notes(obj, note_start, note_end);
|
||||||
|
if (note_map != NULL)
|
||||||
|
munmap(note_map, note_map_len);
|
||||||
munmap(hdr, PAGE_SIZE);
|
munmap(hdr, PAGE_SIZE);
|
||||||
return (obj);
|
return (obj);
|
||||||
|
|
||||||
error1:
|
error1:
|
||||||
munmap(mapbase, mapsize);
|
munmap(mapbase, mapsize);
|
||||||
error:
|
error:
|
||||||
|
if (note_map != NULL && note_map != MAP_FAILED)
|
||||||
|
munmap(note_map, note_map_len);
|
||||||
munmap(hdr, PAGE_SIZE);
|
munmap(hdr, PAGE_SIZE);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user