diff --git a/core/relinker/CMakeLists.txt b/core/relinker/CMakeLists.txt index 89709dc94..74a23a8a0 100644 --- a/core/relinker/CMakeLists.txt +++ b/core/relinker/CMakeLists.txt @@ -465,6 +465,8 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_string_table_bounds.py $) add_test(NAME sce_code_extent COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_sce_code_extent.py $) + add_test(NAME sce_relro COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_sce_relro.py $) add_test(NAME call_registry COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_call_registry.py $) add_test(NAME jmprel_table_bounds COMMAND ${Python3_EXECUTABLE} diff --git a/core/relinker/relinker/src/parsing/ElfReader.cpp b/core/relinker/relinker/src/parsing/ElfReader.cpp index 4b0e8560d..7e5ab3134 100644 --- a/core/relinker/relinker/src/parsing/ElfReader.cpp +++ b/core/relinker/relinker/src/parsing/ElfReader.cpp @@ -130,6 +130,23 @@ std::vector ElfReader::ReadProgramHeaders() const { offset += header.ProgramHeaderEntrySize; } + for (auto& relro : headers) { + if (relro.Type != PT_OS_RELRO || relro.MemorySize == 0) continue; + bool covered = false; + for (const auto& load : headers) { + if (load.Type != PT_LOAD || load.MemorySize == 0) continue; + const bool overlaps = relro.MappedAddress < load.MappedAddress ? load.MappedAddress - relro.MappedAddress < relro.MemorySize : relro.MappedAddress - load.MappedAddress < load.MemorySize; + if (!overlaps) continue; + if (relro.MappedAddress < load.MappedAddress || relro.MemorySize > load.MemorySize - (relro.MappedAddress - load.MappedAddress)) + throw RelinkerException("PT_SCE_RELRO partially overlaps a PT_LOAD segment", relro.MappedAddress); + covered = true; + } + if (!covered) { + relro.Type = PT_LOAD; + relro.Flags = PF_R | PF_W; + } + } + return headers; } diff --git a/core/relinker/relinker/tests/test_sce_relro.py b/core/relinker/relinker/tests/test_sce_relro.py new file mode 100644 index 000000000..bcb878337 --- /dev/null +++ b/core/relinker/relinker/tests/test_sce_relro.py @@ -0,0 +1,74 @@ +import os +from pathlib import Path +import struct +import subprocess +import sys +import tempfile + +from test_linux_dynamic_strings import dynamic_strings, file_offset +from test_linux_load_alignment import loads + +PT_LOAD = 1 +PT_DYNAMIC = 2 +PT_SCE_RELRO = 0x61000010 +PT_SCE_VERSION = 0x6FFFFF01 + + +def fixture(extra): + image = bytearray(0x3000) + image[:16] = b"\x7fELF\x02\x01\x01" + bytes(9) + headers = [(PT_LOAD, 5, 0, 0, 0x1000, 0x1000, 0x1000), *extra] + tags = [(5, 0x600), (10, 1), (6, 0x620), (11, 24), (7, 0x700), (8, 24), (9, 24), (0, 0)] + headers.append((PT_DYNAMIC, 6, 0x400, 0x400, len(tags) * 16, len(tags) * 16, 8)) + headers += [(PT_SCE_VERSION, 0, 0, 0, 0, 0, 1)] * (7 - len(headers)) + struct.pack_into("