diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-05-02 20:27:46 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-02 20:27:46 +0000 |
commit | f87ead523766066e070ab9749751a1772e3fdb52 (patch) | |
tree | d1beb83a8080ea7ade8d8c44f45eb81b7a8b5013 | |
parent | e6b6cc293e8c92d1a13fe3e2b4500db9312b4768 (diff) | |
parent | 617d0278922929191b0b478617fd425bdbd19f64 (diff) | |
download | bionic-build-tools-release.tar.gz |
Merge "Snap for 11794311 from 403ea86b2e1ac3071a17c9ad05acf5b801bfa0d0 to build-tools-release" into build-tools-releasebuild-tools-release
-rw-r--r-- | libc/system_properties/system_properties.cpp | 21 | ||||
-rw-r--r-- | linker/linker_crt_pad_segment_test.cpp | 9 | ||||
-rw-r--r-- | linker/linker_phdr.cpp | 59 | ||||
-rw-r--r-- | linker/linker_phdr.h | 2 | ||||
-rw-r--r-- | tests/clang_fortify_tests.cpp | 8 |
5 files changed, 83 insertions, 16 deletions
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp index 1dedb61e7..e0d38a822 100644 --- a/libc/system_properties/system_properties.cpp +++ b/libc/system_properties/system_properties.cpp @@ -337,31 +337,42 @@ int SystemProperties::Update(prop_info* pi, const char* value, unsigned int len) int SystemProperties::Add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen) { - if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) { + if (namelen < 1) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: name length 0"); return -1; } - if (namelen < 1) { + if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: \"%s\" value too long: %d >= PROP_VALUE_MAX", + name, valuelen); return -1; } if (!initialized_) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: properties not initialized"); return -1; } prop_area* serial_pa = contexts_->GetSerialPropArea(); if (serial_pa == nullptr) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: property area not found"); return -1; } prop_area* pa = contexts_->GetPropAreaForName(name); if (!pa) { - async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name); + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: access denied for \"%s\"", name); return -1; } - bool ret = pa->add(name, namelen, value, valuelen); - if (!ret) { + if (!pa->add(name, namelen, value, valuelen)) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", + "__system_property_add failed: add failed for \"%s\"", name); return -1; } diff --git a/linker/linker_crt_pad_segment_test.cpp b/linker/linker_crt_pad_segment_test.cpp index 5a219f8ee..c11df50fe 100644 --- a/linker/linker_crt_pad_segment_test.cpp +++ b/linker/linker_crt_pad_segment_test.cpp @@ -72,13 +72,22 @@ bool GetPadSegment(const std::string& elf_path) { }; // anonymous namespace TEST(crt_pad_segment, note_absent) { + if (!page_size_migration_supported()) { + GTEST_SKIP() << "Kernel does not support page size migration"; + } ASSERT_FALSE(GetPadSegment("no_crt_pad_segment.so")); } TEST(crt_pad_segment, note_present_and_enabled) { + if (!page_size_migration_supported()) { + GTEST_SKIP() << "Kernel does not support page size migration"; + } ASSERT_TRUE(GetPadSegment("crt_pad_segment_enabled.so")); } TEST(crt_pad_segment, note_present_and_disabled) { + if (!page_size_migration_supported()) { + GTEST_SKIP() << "Kernel does not support page size migration"; + } ASSERT_FALSE(GetPadSegment("crt_pad_segment_disabled.so")); } diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index ef7671cee..fa712a10a 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -46,6 +46,8 @@ #include "private/CFIShadow.h" // For kLibraryAlignment #include "private/elf_note.h" +#include <android-base/file.h> + static int GetTargetElfMachine() { #if defined(__arm__) return EM_ARM; @@ -707,8 +709,28 @@ bool ElfReader::ReserveAddressSpace(address_space_params* address_space) { return true; } +/* + * Returns true if the kernel supports page size migration, else false. + */ +bool page_size_migration_supported() { + static bool pgsize_migration_enabled = []() { + std::string enabled; + if (!android::base::ReadFileToString("/sys/kernel/mm/pgsize_migration/enabled", &enabled)) { + return false; + } + return enabled.find("1") != std::string::npos; + }(); + return pgsize_migration_enabled; +} + // Find the ELF note of type NT_ANDROID_TYPE_PAD_SEGMENT and check that the desc value is 1. bool ElfReader::ReadPadSegmentNote() { + if (!page_size_migration_supported()) { + // Don't attempt to read the note, since segment extension isn't + // supported; but return true so that loading can continue normally. + return true; + } + // The ELF can have multiple PT_NOTE's, check them all for (size_t i = 0; i < phdr_num_; ++i) { const ElfW(Phdr)* phdr = &phdr_table_[i]; @@ -773,7 +795,16 @@ static inline void _extend_load_segment_vma(const ElfW(Phdr)* phdr_table, size_t const ElfW(Phdr)* next = nullptr; size_t next_idx = phdr_idx + 1; - if (phdr->p_align == kPageSize || !should_pad_segments) { + // Don't do segment extension for p_align > 64KiB, such ELFs already existed in the + // field e.g. 2MiB p_align for THPs and are relatively small in number. + // + // The kernel can only represent padding for p_align up to 64KiB. This is because + // the kernel uses 4 available bits in the vm_area_struct to represent padding + // extent; and so cannot enable mitigations to avoid breaking app compatibility for + // p_aligns > 64KiB. + // + // Don't perform segment extension on these to avoid app compatibility issues. + if (phdr->p_align <= kPageSize || phdr->p_align > 64*1024 || !should_pad_segments) { return; } @@ -887,10 +918,28 @@ bool ElfReader::LoadSegments() { // 2) Break the COW backing, faulting in new anon pages for a region // that will not be used. - // _seg_file_end = unextended seg_file_end - uint64_t _seg_file_end = seg_start + phdr->p_filesz; - if ((phdr->p_flags & PF_W) != 0 && page_offset(_seg_file_end) > 0) { - memset(reinterpret_cast<void*>(_seg_file_end), 0, kPageSize - page_offset(_seg_file_end)); + uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz; + if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) { + memset(reinterpret_cast<void*>(unextended_seg_file_end), 0, + kPageSize - page_offset(unextended_seg_file_end)); + } + + // Pages may be brought in due to readahead. + // Drop the padding (zero) pages, to avoid reclaim work later. + // + // NOTE: The madvise() here is special, as it also serves to hint to the + // kernel the portion of the LOAD segment that is padding. + // + // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411 + // [2] https://android-review.googlesource.com/c/kernel/common/+/3048835 + uint64_t pad_start = page_end(unextended_seg_file_end); + uint64_t pad_end = page_end(seg_file_end); + CHECK(pad_start <= pad_end); + uint64_t pad_len = pad_end - pad_start; + if (page_size_migration_supported() && pad_len > 0 && + madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) { + DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m", + name_.c_str(), pad_start, pad_len); } seg_file_end = page_end(seg_file_end); diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index 61242eb4c..aab9018b4 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -154,3 +154,5 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias); + +bool page_size_migration_supported(); diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp index 544af4308..f4ef4ac4a 100644 --- a/tests/clang_fortify_tests.cpp +++ b/tests/clang_fortify_tests.cpp @@ -164,9 +164,7 @@ FORTIFY_TEST(string) { const char large_string[] = "Hello!!!"; static_assert(sizeof(large_string) > sizeof(small_buffer), ""); -#if __clang_major__ > 13 - // expected-error@+3{{will always overflow}} -#endif + // expected-error@+2{{will always overflow}} // expected-error@+1{{string bigger than buffer}} EXPECT_FORTIFY_DEATH(strcpy(small_buffer, large_string)); // expected-error@+1{{string bigger than buffer}} @@ -204,9 +202,7 @@ FORTIFY_TEST(string) { static_assert(sizeof(small_string) > sizeof(split.tiny_buffer), ""); #if _FORTIFY_SOURCE > 1 -#if __clang_major__ > 13 - // expected-error@+4{{will always overflow}} -#endif + // expected-error@+3{{will always overflow}} // expected-error@+2{{string bigger than buffer}} #endif EXPECT_FORTIFY_DEATH_STRUCT(strcpy(split.tiny_buffer, small_string)); |