Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit d990f7d

Browse files
smore-loreGerrit Code Review
authored andcommitted
Merge "Linker: clear error for incorrect page size load." into main
2 parents 6e06348 + fc89c8a commit d990f7d

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

linker/linker_phdr.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,7 @@ size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phd
567567
continue;
568568
}
569569

570-
if (phdr->p_align > maximum_alignment) {
571-
maximum_alignment = phdr->p_align;
572-
}
570+
maximum_alignment = std::max(maximum_alignment, static_cast<size_t>(phdr->p_align));
573571
}
574572

575573
#if defined(__LP64__)
@@ -579,6 +577,30 @@ size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phd
579577
#endif
580578
}
581579

580+
// Returns the minimum p_align associated with a loadable segment in the ELF
581+
// program header table. Used to determine if the program alignment is compatible
582+
// with the page size of this system.
583+
size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) {
584+
size_t minimum_alignment = page_size();
585+
586+
for (size_t i = 0; i < phdr_count; ++i) {
587+
const ElfW(Phdr)* phdr = &phdr_table[i];
588+
589+
// p_align must be 0, 1, or a positive, integral power of two.
590+
if (phdr->p_type != PT_LOAD || ((phdr->p_align & (phdr->p_align - 1)) != 0)) {
591+
continue;
592+
}
593+
594+
if (phdr->p_align <= 1) {
595+
continue;
596+
}
597+
598+
minimum_alignment = std::min(minimum_alignment, static_cast<size_t>(phdr->p_align));
599+
}
600+
601+
return minimum_alignment;
602+
}
603+
582604
// Reserve a virtual address range such that if it's limits were extended to the next 2**align
583605
// boundary, it would not overlap with any existing mappings.
584606
static void* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size_t start_align,
@@ -830,6 +852,15 @@ static inline void _extend_load_segment_vma(const ElfW(Phdr)* phdr_table, size_t
830852
}
831853

832854
bool ElfReader::LoadSegments() {
855+
size_t min_palign = phdr_table_get_minimum_alignment(phdr_table_, phdr_num_);
856+
// Only enforce this on 16 KB systems. Apps may rely on undefined behavior
857+
// here on 4 KB systems, which is the norm before this change is introduced.
858+
if (kPageSize >= 16384 && min_palign < kPageSize) {
859+
DL_ERR("\"%s\" program alignment (%zu) cannot be smaller than system page size (%zu)",
860+
name_.c_str(), min_palign, kPageSize);
861+
return false;
862+
}
863+
833864
for (size_t i = 0; i < phdr_num_; ++i) {
834865
const ElfW(Phdr)* phdr = &phdr_table_[i];
835866

linker/linker_phdr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
126126
ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
127127

128128
size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
129+
size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
129130

130131
int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
131132
ElfW(Addr) load_bias, bool should_pad_segments,

0 commit comments

Comments
 (0)