@@ -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.
584606static 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
832854bool 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
0 commit comments