rtld: Round down relro_size

lld rounds up p_memsz(PT_GNU_RELRO) to satisfy common-page-size. If the
page size is smaller than common-page-size, rounding up relro_size may
incorrectly make some RW pages read-only.

GNU ld, gold, and ld.lld ensures p_vaddr+p_memsz is a multiple of
common-page-size. While max-page-size >= system the page size,
common-page-size can be smaller than the system page size.

Submitted by:	MaskRay
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D31498
This commit is contained in:
Konstantin Belousov 2021-08-12 05:45:15 +03:00
parent 44d4804d19
commit c9f833abf1
2 changed files with 4 additions and 2 deletions

View File

@ -325,7 +325,8 @@ map_object(int fd, const char *path, const struct stat *sb)
} }
obj->stack_flags = stack_flags; obj->stack_flags = stack_flags;
obj->relro_page = obj->relocbase + trunc_page(relro_page); obj->relro_page = obj->relocbase + trunc_page(relro_page);
obj->relro_size = round_page(relro_size); obj->relro_size = trunc_page(relro_page + relro_size) -
trunc_page(relro_page);
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) if (note_map != NULL)

View File

@ -1557,7 +1557,8 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
case PT_GNU_RELRO: case PT_GNU_RELRO:
obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr);
obj->relro_size = round_page(ph->p_memsz); obj->relro_size = trunc_page(ph->p_vaddr + ph->p_memsz) -
trunc_page(ph->p_vaddr);
break; break;
case PT_NOTE: case PT_NOTE: