Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ELF] Align the end of PT_GNU_RELRO associated PT_LOAD to a common-page-size boundary #66042

Merged
merged 1 commit into from Sep 14, 2023

Commits on Sep 14, 2023

  1. [ELF] Align the end of PT_GNU_RELRO associated PT_LOAD to a common-pa…

    …ge-size boundary
    
    Close llvm#57618: currently we align the end of PT_GNU_RELRO to a common-page-size
    boundary, but do not align the end of the associated PT_LOAD. This is benign
    when runtime_page_size >= common-page-size.
    
    However, when runtime_page_size < common-page-size, it is possible that
    `alignUp(end(PT_LOAD), page_size) < alignDown(end(PT_GNU_RELRO), page_size)`.
    In this case, rtld's mprotect call for PT_GNU_RELRO will apply to unmapped
    regions and lead to an error, e.g.
    
    ```
    error while loading shared libraries: cannot apply additional memory protection after relocation: Cannot allocate memory
    ```
    
    To fix the issue, add a padding section .relro_padding like mold, which
    is contained in the PT_GNU_RELRO segment and the associated PT_LOAD
    segment. The section also prevents strip from corrupting PT_LOAD program
    headers.
    
    .relro_padding has the largest `sortRank` among RELRO sections.
    Therefore, it is naturally placed at the end of `PT_GNU_RELRO` segment
    in the absence of `PHDRS`/`SECTIONS` commands.
    
    In the presence of `SECTIONS` commands, we place .relro_padding
    immediately before a symbol assignment using DATA_SEGMENT_RELRO_END (see
    also https://reviews.llvm.org/D124656), if present.
    DATA_SEGMENT_RELRO_END is changed to align to max-page-size instead of common-page-size.
    
    Some edge cases worth mentioning:
    
    * ppc64-toc-addis-nop.s: when PHDRS is present, do not append .relro_padding
    * avoid-empty-program-headers.s: when the only RELRO section is .tbss,
      it is not part of PT_LOAD segment, therefore we do not append .relro_padding.
    
    ---
    
    Close llvm#65002: GNU ld from 2.39 onwards aligns the end of PT_GNU_RELRO to a
    max-page-size boundary (https://sourceware.org/PR28824) so that the last page is
    protected even if runtime_page_size > common-page-size.
    
    In my opinion, losing protection for the last page when the runtime page size is
    larger than common-page-size is not really an issue. Double mapping a page of up
    to max-common-page for the protection could cause undesired VM waste. Internally
    we had users complaining about 2MiB max-page-size applying to shared objects.
    
    Therefore, the end of .relro_padding is padded to a common-page-size
    boundary. Users who are really anxious can set common-page-size to match
    their runtime page size.
    
    ---
    
    17 tests need updating as there are lots of change detectors.
    MaskRay committed Sep 14, 2023
    Copy the full SHA
    04cc6bb View commit details
    Browse the repository at this point in the history